0

I want to write unit tests for the following class:

public class Target() { private final Member member = new Member(); public Target() { } } 

I want to initialize this Target class with a mocked instance of Member, as it is not feasible to instantiate Member during testing. Is that possible with any framework?

EDIT:

I do not want to mock Target class. I intend to mock Member class at the time of initialization.

Object method() { member.differentMethod(); //Logic which I want to test } 

Please suggest how to mock this call to the method of Member class.

6
  • Yes your easymock/mocito/powermock framework. But are you just interested in mocking framework or you want to test Target class itself? Commented Jan 2, 2016 at 12:06
  • I wish to test the Target class. However, whenever I try to initialize Target(), I receive an error, as it internally calls Member(), and that requires setting up loads of resources which I want to avoid. I know how to initialize classes with mocked objects using constructors with arguments. But I don't have a clue how to do that in this case. Commented Jan 2, 2016 at 12:10
  • Doesnt makes sense but mocking Target class, how are you going to test target class itself? Commented Jan 2, 2016 at 12:11
  • There is some misunderstanding. I do not want to mock the Target class, but the Member class within it. Updated the description. Commented Jan 2, 2016 at 12:17
  • Instead of using such an implicit dependency and tight binding, pass the Member object as parameter to the constructor (constructor injection). That way you can pass a mocked Member in your unit test. Commented Jan 2, 2016 at 12:20

3 Answers 3

2

To build off of Prim's answer (upvoted), just give yourself two constructors.

public class Target() { private final Member member; public Target() { this.member = new Member(); } /** Testing constructor. Package-private visibility for tests in the same package. */ Target(Member member) { this.member = member; } } 

By supplying multiple constructors, you ensure your consumers in production will not have to change at all. This is also a distinct case from "testing code polluting production": One of your use-cases (specifically a test) requires a custom implementation of Member, and you are providing the most-encapsulated access for the replacement of that member as spec'ed.

See also: How to use Mockito when we cannot pass a mock object to an instance of a class

Sign up to request clarification or add additional context in comments.

Comments

1

You can use constructor mocking with Powermock:

@RunWith(PowerMockRunner.class) @PrepareForTest(Target.class) public class Test { @Test public void doSomething() throws Exception { Member mockMember = mock(Member.class); PowerMockito.whenNew(Member.class).thenReturn(mockMember); Target thisTargetWillHaveYourMockAsField = new Target(); //Your test code } } 

2 Comments

This is what I was looking for! Works perfectly for my case. No need to change the class design for testing.
Great to hear it helped. Thanks for accepting the answer. Cu.
1

You should pass the instance of Member use by Target class into contructor of Target class.

By doing that, you can use the implementation of you Member class in production environment, and use one another implementation (which may be empty) in test environment.

The best and optimal solution is to use Dependency Inversion/Injection principle

3 Comments

Yes, I am aware of that method. But is there a way to do this without changing the NoArgsConstructor?
You can use no args constructor in Target, by implementing a provider class which delegates the creation of Member instance and by returning different implementations according to production or test environment
Well, I guess I have to somehow change the way the Target class is designed to properly test it. Either by changing the constructor, or having a provider class or factory for initializing Member. Lets see if someone comes up with a solution without essentially requiring changes in the Target class.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.