I would like to unit test a function that takes a certain object as input,
processes it and when it finished, the state of that object should have been changed to a certain value.
As I want to do "real" unit testing (as I understand it), I only want to use the class that is providing the processing function,
and mock all other classes used.
To fulfill this requirement I need to mock the object that is being processed; but when it is only a mock, it has no real state anymore that could be changed.
Example pseudocode:
object = createMock('SomeClassName');
object.whenReceives('getState').shouldReturn(0);
Processor.process(object);
assertEquals(expected = 1, actual = object.getState());
The problem is that I need to mock the "getState" method to prepare the starting state for the test, and so
afterwards I cannot use the real method anymore.
Do you know how can I achieve this, or how I should change the design of the test?
PS: I am actually using PHPUnit and Mockery.
Thank you for any advice.
You are not deal with real object so you don't ask to the object the changed value but you can assert that someone dial with it for change the state. As Example:
$mock = Mockery::mock($class);
// Check that someone call the getstate method only one time
$mock
->shouldReceive('getState')
->once()
->andReturn(0);
// Check that someone call change the state method
$mock
->shouldReceive('setState')
->once()
->with(1);
Further reference:
http://code.tutsplus.com/tutorials/mockery-a-better-way--net-28097
http://culttt.com/2013/07/22/getting-started-with-mockery/
hope this help
Related
I have seen how to test observable using TestSubscriber but I have no idea how to test Completable.doOnSuccess callback. Specifically this method:
fun setAuthToken(authToken: AuthToken): Completable {
this.authToken = authToken
return Completable.fromSingle<User>(api
.getCurrentUser()
.doOnSuccess {
user = it
})
}
This is not something that might not need to be tested with RxJava test subscribers at all (depending on the rest of the code).
Remember - you don't want to test internal state, or at least do it as rarely as possible. Internal state and class structure can change and it will probably change often. So it's bad practice to check if user is assigned to the field.
So you could make Completable blocking and then assert state of (let’s call it ‚server’) server class, but I would highly discourage doing it this way:
server.setAuthToken(AuthToken("token"))
.blockingAwait()
assertThat(server.user, equalTo(expectedUser))
What you want to test is behavior.
You are probably not assigning user to the field just for the sake of having some fields. You are doing it to use information from user later on. So first you should call setAuthToken and then call function that really uses information from the user. Then you can assert if used information is correct and is coming from correct user.
So sample tests (depending on the class) could look like this:
server.setAuthToken(AuthToken("token"))
.andThen(server.sendRequest())
.blockingAwait()
// assert if correct user info was sent
or
server.setAuthToken(AuthToken("token"))
.andThen(server.sendRequest())
.test()
// assert if correct user info was sent
I know stubs verify state and the mocks verify behavior.
How can I make a mock in PHPUnit to verify the behavior of the methods? PHPUnit does not have verification methods (verify()), And I do not know how to make a mock in PHPUnit.
In the documentation, to create a stub is well explained:
// Create a stub for the SomeClass class.
$stub = $this->createMock(SomeClass::class);
// Configure the stub.
$stub
->method('doSomething')
->willReturn('foo');
// Calling $stub->doSomething() will now return 'foo'.
$this->assertEquals('foo', $stub->doSomething());
But in this case, I am verifying status, saying that return an answer.
How would be the example to create a mock and verify behavior?
PHPUnit used to support two ways of creating test doubles out of the box. Next to the legacy PHPUnit mocking framework we could choose prophecy as well.
Prophecy support was removed in PHPUnit 9, but it can be added back by installing phpspec/prophecy-phpunit.
PHPUnit Mocking Framework
The createMock method is used to create three mostly known test doubles. It's how you configure the object makes it a dummy, a stub, or a mock.
You can also create test stubs with the mock builder (getMockBuilder returns the mock builder). It's just another way of doing the same thing that lets you to tweak some additional mock options with a fluent interface (see the documentation for more).
Dummy
Dummy is passed around, but never actually called, or if it's called it responds with a default answer (mostly null). It mainly exists to satisfy a list of arguments.
$dummy = $this->createMock(SomeClass::class);
// SUT - System Under Test
$sut->action($dummy);
Stub
Stubs are used with query like methods - methods that return things, but it's not important if they're actually called.
$stub = $this->createMock(SomeClass::class);
$stub->method('getSomething')
->willReturn('foo');
$sut->action($stub);
Mock
Mocks are used with command like methods - it's important that they're called, and we don't care much about their return value (command methods don't usually return any value).
$mock = $this->createMock(SomeClass::class);
$mock->expects($this->once())
->method('doSomething')
->with('bar');
$sut->action($mock);
Expectations will be verified automatically after your test method finished executing. In the example above, the test will fail if the method doSomething wasn't called on SomeClass, or it was called with arguments different to the ones you configured.
Spy
Not supported.
Prophecy
Prophecy is now supported by PHPUnit out of the box, so you can use it as an alternative to the legacy mocking framework. Again, it's the way you configure the object makes it becomes a specific type of a test double.
Dummy
$dummy = $this->prophesize(SomeClass::class);
$sut->action($dummy->reveal());
Stub
$stub = $this->prophesize(SomeClass::class);
$stub->getSomething()->willReturn('foo');
$sut->action($stub->reveal());
Mock
$mock = $this->prophesize(SomeClass::class);
$mock->doSomething('bar')->shouldBeCalled();
$sut->action($mock->reveal());
Spy
$spy = $this->prophesize(SomeClass::class);
// execute the action on system under test
$sut->action($spy->reveal());
// verify expectations after
$spy->doSomething('bar')->shouldHaveBeenCalled();
Dummies
First, look at dummies. A dummy object is both what I look like if you ask me to remember where I left the car keys... and also the object you get if you add an argument with a type-hint in phpspec to get a test double... then do absolutely nothing with it. So if we get a test double and add no behavior and make no assertions on its methods, it's called a "dummy object".
Oh, and inside of their documentation, you'll see things like $prophecy->reveal(). That's a detail that we don't need to worry about because phpspec takes care of that for us. Score!
Stubs
As soon as you start controlling even one return value of even one method... boom! This object is suddenly known as a stub. From the docs: "a stub is an object double" - all of these things are known as test doubles, or object doubles - that when put in a specific environment, behaves in a specific way. That's a fancy way of saying: as soon as we add one of these willReturn() things, it becomes a stub.
And actually, most of the documentation is spent talking about stubs and the different ways to control exactly how it behaves, including the Argument wildcarding that we saw earlier.
Mocks
If you keep reading down, the next thing you'll find are "mocks". An object becomes a mock when you call shouldBeCalled(). So, if you want to add an assertion that a method is called a certain number of times and you want to put that assertion before the actual code - using shouldBeCalledTimes() or shouldBeCalled() - congratulations! Your object is now known as a mock.
Spies
And finally, at the bottom, we have spies. A spy is the exact same thing as a mock, except it's when you add the expectation after the code - like with shouldHaveBeenCalledTimes().
https://symfonycasts.com/screencast/phpspec/doubles-dummies-mocks-spies
I am using creating an application using mapreduce2 and testing the same using MRUnit 1.1.0. In one of the tests, I am checking the output of a reducer which puts the 'current system time' in it's output. I.e. at the time the reducer executes, the timestamp is used in context.write() to be written along with the rest of the output. Now even though I use the same method to find the system time in the test method as the one I use in the reducer, the times calculated in both are generally a second apart, like 2016-05-31 19:10:02 and 2016-05-31 19:10:01. So the output in the two turns out to be different, example:
test_fe01,2016-05-31 19:10:01
test_fe01,2016-05-31 19:10:02
This causes an assertion error. I wish to ignore this difference in timestamps, so the tests pass if the rest of the output apart from the timestamp is matched. I am looking for a way to mock the method used for returning the system time, so that a hardcoded value is returned, and the reducer and the test both use this mocked method during the test. Is this possible to do? Any help will be appreciated.
Best Regards
EDIT: I have already tried Mockito's spy functionality in the my test:
MClass mc = Mockito.spy(new MClass());
Mockito.when(mc.getSysTime()).thenReturn("FakeTimestamp");
However, this gives a runtime error:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
It is a limitation of the mock engine.
The method getSysTime() is public and static and class MClass is public and doesn't have any parent classes.
Assuming i understand your question, you could pass a time into the Reduce using the configuration object. In your reduce you could check if this configuration is set and use it, otherwise you use the system time.
This way you can pass in a known value for testing and assert you get that same value back.
I have code that uses a Singleton (this happens to be for a website, so the Singleton has the scope of just that one Request; each Request will have their own singleton).
My code (which happens to be in an HttpModule) does the following:
1 - Checks if the Singleton object is null and, if so, initializes it.
2 - Updates a property on this singleton object along the lines of:
if(A)
{
SingletonHolder.Current.X = Y;
}
else
{
SingletonHolder.Current.X = Z;
}
I then want to have some unit tests around this method to check that logic is correct. Let's say for argument's sake that we want the following 4 tests:
GivenMethodCall_WhenA_ThenXSetToY
GivenMethodCall_WhenA_ThenXNotSetToZ
GivenMethodCall_WhenNotA_ThenXSetToZ
GivenMethodCall_WhenNotA_ThenXNotSetToY
These tests all work perfectly when run one-at-a-time, but when run in VS2013 with the NUnit test runner then we get some failures because each test is run in parallel and the method under test is updating the same singleton object's property with different values.
Any advice on a pattern that would solve this?
Thanks
Griff
You probably just need to provide a method within your test fixture decorated with the SetUpAttribute method to perform initial setup before each test method is run and another method decorated with the TearDownAttribute that runs after each test method. The documentation for the nUnit SetUpAttribute is found here.
This will allow you to (in your SetUp method) initialize your Singleton object, and then (in your TearDown method) to set your Singleton object to null so that SetUp can re-instantiate/initialize the object for the next test.
I want to test the in case of some fail no method will be called on a mock object , using google mock.
so the code be something like:
auto mocObj = new MockObj;
EXPECT_NO_METHOD_CALL(mocObj); //this is what I'm locking for
auto mainObj = new MainObj(mocObj , ......and other mocks); // here I simulate a fail using the other mock objects, and I want to be sure the no methods are called on the mockObj
There are no needs to explicitly tell that no methods will be called. If you set the logging level high enough, you should get a message if a method is called (if no expectation is set).
Other then that, you can set expectations like this :
EXPECT_CALL( mockObj, Foo(_) ).Times(0);
on all methods.
Create a StrictMock; any unexpected method call will be a failure.
Use Exactly(0) for all your class methods.
the cardinality will be set to zero so you are expecting no calls
You can also use StrictMock instead of NiceMock. This will fail on any "uninteresting" call, i.e., whenever a method of the mock is called, but no EXPECT_CALL was defined.
See Google Mock documentation here.