How do you assert a generic method was called with Rhino Mocks? - unit-testing

I have the following test to verify that my repository is calling it's respective session (I've rewritten it to highlight the actual problem):
[Test]
public void Why_Does_This_Fail()
{
var objectUnderTest = new SomeGenericsProblem();
var fakeSession = MockRepository.GenerateMock<ISession>();
fakeSession.Expect(s => s.Query<SomeClass>());
objectUnderTest.NotWorking<SomeClass>();
fakeSession.AssertWasCalled(t => t.Query<SomeClass>());
}
but when I run the test I get this:
System.InvalidOperationException :
Invalid call, the last call has been
used or no call has been made (make
sure that you are calling a virtual
(C#) / Overridable (VB) method).(C#) / Overridable (VB) method).
Any ideas what I'm doing wrong here? The session that I'm mocking is an interface, so it has to be virtual/overridable.
I have a feeling it has something to do with the fact that my Query method is a generic, but I don't know any other way to express what I'm trying to test.
Also, If I remove the part that sets up the expectation (i.e. this line of code:)
fakeSession.Expect(s => s.Query<SomeClass>());
I get a different exception which is equally confusing to me:
System.InvalidOperationException : No
expectations were setup to be
verified, ensure that the method call
in the action is a virtual (C#) /
overridable (VB.Net) method calloverridable (VB.Net) method call

So I figured out what was wrong.
ISession comes from NHibernate, which I probably should have mentioned.
The reason why this is cruicialy important is because
session.Query<T>
(which is what I'm trying to mock), is an EXTENSION METHOD.
Rhino Mocks apparently does not have the capability of mocking extension methods, hence why it's giving me the weird error.
So hopefully I'll have saves someone else the time and agony I've gone through in trying to figure out why my test won't pass.
The only solution that I've read about for this is to actually change the design of the extension method (which I can't do because it's part of NHibernate), or to use a different mocking framework like TypeMock.

[Test]
public void Query_WhenCalled_CallsSessionQuery()
{
// arrange
var session = MockRepository.GenerateStub<ISession>();
var r = new Repository(session);
// act
r.Query<SomeClass>();
// assert
session.AssertWasCalled(s => s.Query<SomeClass>());
}

Related

Mockito gives UnfinishedVerificationException when it seems OK

Mockito appears to be throwing an UnfinishedVerificationException when I think I've done everything correctly. Here's my partial test case:
HttpServletRequest req = mock(HttpServletRequest.class);
when(req.getHeader("Authorization")).thenReturn("foo");
HttpServletResponse res = mock(HttpServletResponse.class);
classUnderTest.doMethod(req, res); // Use the mock
verify(res, never());
verify(req).setAttribute(anyString(), anyObject());
And here's the partial class and method:
class ClassUnderTest extends AnotherClass {
#Override
public String doMethod(ServletRequest req, ServletRequest res) {
// etc.
return "someString";
}
}
Ignoring the fact that you should never mock interfaces you don't own, why is Mockito giving me the following message?
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-> at (redacted)
Example of correct verification:
verify(mock).doSomething()
Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
at [test method name and class redacted]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
... etc
This might also be caused if you try to verify a method which expects primitive arguments with any():
For example, if our method has this signature:
method(long l, String s);
And you try to verify it like this, it will fail with aforementioned message:
verify(service).method(any(), anyString());
Change it to anyLong() and it will work:
verify(service).method(anyLong(), anyString());
I just came across this my self and it caused me a lot of confusion.
As David mentioned above Mockito reports errors in the next Mockito method call which may not be in the same test method. While the exception message does contain a reference to the actual place the error occurred I find having incorrect tests failing counter productive to the testing process. And the simpler the tests the more likely an error is to show up in the next test!
Here is an easy fix that will ensure errors appear in the correct test method:
#After
public void validate() {
validateMockitoUsage();
}
From the Mockito documentation here:
Mockito throws exceptions if you misuse it so that you know if your
tests are written correctly. The gotcha is that Mockito does the
validation next time you use the framework (e.g. next time you verify,
stub, call mock etc.). But even though the exception might be thrown
in the next test, the exception message contains a navigable stack
trace element with location of the defect. Hence you can click and
find the place where Mockito was misused.
Sometimes though, you might
want to validate the framework usage explicitly. For example, one of
the users wanted to put validateMockitoUsage() in his #After method so
that he knows immediately when he misused Mockito. Without it, he
would have known about it not sooner than next time he used the
framework. One more benefit of having validateMockitoUsage() in #After
is that jUnit runner will always fail in the test method with defect
whereas ordinary 'next-time' validation might fail the next test
method. But even though JUnit might report next test as red, don't
worry about it and just click at navigable stack trace element in the
exception message to instantly locate the place where you misused
mockito.
I was getting this same error due to using any() with a boolean parameter, when apparently it needed to be anyBoolean().
In my case, using kotlin was because the funcion to test was not declared as open.
The exception notices that no final/private/equals/hash methods can be used.
fun increment(){
i++
}
to
open fun increment(){
i++
}
With Junit 5, you can add the following to show more meaningful Mockito exceptions in the console
#AfterEach
public void validate() {
validateMockitoUsage()
}
Also see this answer: https://stackoverflow.com/a/22550055/8073652
I had similar exception with class MyRepository
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-> at MyRepository$$FastClassBySpringCGLIB$$de8d8358.invoke()
Example of correct verification:
verify(mock).doSomething()
The problem was resolved when I created interface for MyRepository, and mock interface, but not implementation.
It seems spring creates some CGLIB proxies and it leads to UnfinishedVerificationException exception.
For me the issue turned out to be a missing bean declaration in the test context xml. It was for a custom aspect class used by another class, an instance of which is a parameter to the constructor of the class which is the parameter to failing verify() call. So I added the bean declaration to the context xml and it worked fine after that.
Changed to #RunWith(PowerMockRunner.class) and the issue went away.
Was using #RunWith(MockitoJUnitRunner.class) earlier.
Hope that helps someone..
I had the same issue, too, on the following stack:
Kotlin
Junit 4.13
Mockito 2.28.2 + Mockito-Inline 2.13.0
Robolectric 4.3.1
I tried to verify a lambda call:
#RunWith(RobolectricTestRunner::class)
class MainViewTest {
#get:Rule
val mockitoRule: MockitoRule = MockitoJUnit.rule()
#Mock private lateinit var mockClickCallback: () -> Unit
#Test
fun `should call clickCallback on the button click`() {
val activity = Robolectric.buildActivity(MainActivity::class.java).create().get()
val viewUnderTest = MainView(activity)
viewUnderTest.setClickCallback(mockClickCallback)
viewUnderTest.button.performClick()
verify(mockClickCallback).invoke() // UnfinishedVerificationException
}
}
Then I found the issue on Github, it seems that the problem is in Robolectric. I used the following workaround:
#RunWith(RobolectricTestRunner::class)
class MainViewTest {
private interface UnitFunction: () -> Unit
#Test
fun `should call clickCallback on the button click`() {
val activity = Robolectric.buildActivity(MainActivity::class.java).create().get()
val viewUnderTest = MainView(activity)
val mockClickCallback = mock(UnitFunction::class.java) as () -> Unit
viewUnderTest.setClickCallback(mockClickCallback)
viewUnderTest.button.performClick()
verify(mockClickCallback).invoke() // OK
}
}
Two answers above suggested using validateMockitoUsage() method after each test.
While this is correct I found that annotating your class with #ExtendWith(MockitoExtension.class)
in Junit 5 give the same effect while adding some the nice Mockito functionalities. Also, it looks cleaner to me as well.
I guess Junit 4 #RunWith(MockitoJUnitRunner.class) will give a similar result but I didn't test it.
I had a similar problem, i found a way to solve this. Mock objects which you for verify haven't been reseted, so you should reset it .You can reset(mock) before your test case function, it may be helpful.
If you try to verify a private or package-private method with Mockito.verify you will get this error.
If you don't want to use PowerMockito you can set your method as protected and I advise you to add the #VisibleForTesting tag:
Before:
void doSomething() {
//Some behaviour
}
After :
#VisibleForTesting
protected void doSomething() {
//Some behaviour
}
I was having the same error
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-at com.xxx.MyTest.testRun_Should_xxx_When_yyy(MyTest.java:127)
Example of correct verification:
verify(mock).doSomething()
Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
at com.xxx.MyTest.validate(MyTest.java:132)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.internal.runners.MethodRoadie.runAfters(MethodRoadie.java:145)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:99)
...
In my case, the error was generated because I was using a PowerMockito.verifyStatic() before my Mockito.verify(...) call, then I had to move the PowerMockito.verifyStatic() to last line (or delete it).
From:
PowerMockito.verifyStatic();
Mockito.verify(myMock, Mockito.times(1)).myMockedMethod(anyString(), anyString(), anyString(), any(XXX.class), any(YYY.class), any(ZZZ.class));
To:
Mockito.verify(myMock, Mockito.times(1)).myMockedMethod(anyString(), anyString(), anyString(), any(XXX.class), any(YYY.class), any(ZZZ.class));
PowerMockito.verifyStatic();
Here is my grain of salt!
I discovered there is a conflict between Mockito and Hibernate Validation.
My solution is the separate my contract checks (#NotNull, #NotEmpty, etc) from the mockito tests. I also started using validateMockitoUsage() to ensure everything was run correctly.
The tests run individually well but while running integration test suite it fails with the UnfinishedVerificationException. The issue arises when we use verify() from mockito and have #EnableRetry.
Workaround for this is to use
public static <T> T unwrapAndVerify(T mock, VerificationMode mode) {
return ((T) Mockito.verify(AopTestUtils.getTargetObject(mock), mode));
}
as mentioned in Mocked Spring #Service that has #Retryable annotations on methods fails with UnfinishedVerificationException
I'm not sure where are your "classUnderTest" come from, but please keep sure it's mocked, not a real one.
I have the same issue for my test case below:
MyAgent rpc = new MyAgent("myNodeName");
...
rpc.doSomething();
...
PowerMockito.verifyPrivate(rpc).invoke("initPowerSwitch");
PowerMockito.verifyPrivate(rpc).invoke("init", "192.168.0.23", "b2", 3);
But it's disappeared for the following test case:
MyAgent rpc = PowerMockito.spy(new MyAgent("myNodeName"));
...
rpc.doSomething();
...
PowerMockito.verifyPrivate(rpc).invoke("initPowerSwitch");
PowerMockito.verifyPrivate(rpc).invoke("init", "192.168.0.23", "b2", 3);
Attention, the Object rpc should be mocked by PowerMockito.spy(...).
Faced same exception when used mockStatic method and called Mockito.verify multiple times, but passed interface instead of implementing class.
wrong code:
try (MockedStatic<Service> staticMock = Mockito.mockStatic(Service.class, Mockito.CALLS_REAL_METHODS)) {
staticMock.verify(() -> ServiceImpl.method()); // passed without errors
staticMock.verify(() -> ServiceImpl.method()); // throws UnfinishedVerificationException
}
fixed code:
try (MockedStatic<ServiceImpl> staticMock = Mockito.mockStatic(Service.class, Mockito.CALLS_REAL_METHODS)) {
staticMock.verify(() -> ServiceImpl.method());
staticMock.verify(() -> ServiceImpl.method());
}
It was my mistake obviosly, but UnfinishedVerificationException message was not helpfull

CakePHP test behaviour with mapped method

Whilst creating an OwnableBehavior I decided to use the $mapMethods property that is available. It is to map any method called isOwnedByXXX() to isOwnedBy() (The link for the documentation on this is here)
Here is my OwnableBehavior code:
class OwnableBehavior extends Model Behavior {
public $mapMethods = array('/isOwnedBy(\w+)/' => 'isOwnedBy');
public function isOwnedBy(Model $model, $type, $id, Model $userModel, $userId) {
// Method is currently empty
}
}
Here is the TestCase code:
class OwnableBehaviorTest extends CakeTestCase {
public function testIsOwned() {
$TestModel = new Avatar();
$TestModel->Behaviors->attach('Ownable');
$result = $TestModel->Behaviors->Ownable->isOwnedByUser(
$TestModel, 1, new User(), 1);
$this->assertTrue($result);
}
}
When I run the test I get this error:
Call to undefined method OwnableBehavior::isOwnedByUser()
If I change the method call to isOwnedBy($TestModel, 'user', 1, new User(), 1); this works, so it looks like for some reason the mapped methods aren't working during the unit test. I have tested the mapped methods in a controller and I get no errors.
I wondered if it was down to how I was loading the behaviour into the model. I couldn't find any documentation in the cookbook on how to properly test Behaviours like there is with Components, Helpers, etc... So I just used the same techniques that the Core Behaviour tests use (Found in Cake/Test/Case/Model/Behavior/).
I did think maybe it could have been down to the fact that I am overwriting the ModelBehavior::setup() method, but I tried adding parent::setup($model, $settings) at the start of the setup method and I still get the same error. I am not overwriting any of the other ModelBehavior methods.
I guess I could just use the OwnableBehavior::isOwnedBy() method, but I'd quite like to know if I could get the mapped methods to work during a unit test.
The solution I have found is replacing this line:
$result = $TestModel->Behaviors->Ownable->isOwnedByUser(...);
with:
$result = $TestModel->isOwnedByUser(...);
So it's just a case of using it more like you would in the application, calling the behaviour method directly from the model. I don't know if this ruins the idea of a unit test and makes it more into integration testing though.

RhinoMocks - Getting the value passed into an Indexer (this[])

I need to find out the value passed into an indexer.
My code (c#) that I need to test is as follows:
string cacheKey = GetCacheKey(cacheKeyRequest);
string cachedValue = myCache[cacheKey] as string;
So, I need to be able to identify the value of the "cacheKey" that was passed into the indexer.
I have attempted this using a Mock of the cache object:
var cache = MockRepository.GenerateMock<WebDataCache>();
The idea being that after the code had executed, I would query the mock to identify the value that had been passed into the indexer:
var actualCacheKey = cache.GetArgumentsForCallsMadeOn(a => a["somevalue"], opt => opt.IgnoreArguments())[0][0].ToString();
This gives me a compilation error: Only assignment, call, increment, decrement, and new object expressions can be used as a statement.
I saw one suggestion to make this a function in the following way:
var actualCacheKey = cache.GetArgumentsForCallsMadeOn(a => a["somevalue"] = null, opt => opt.IgnoreArguments())[0][0].ToString();
This now compiles,but throws a run-time InvalidOperationException: No expectations were setup to be verified, ensure that the method call in the action is a virtual (C#) / overridable (VB.Net) method call.
Any suggestions? [Am using RhinoMocks.3.6.1]
Many thanks in advance
Griff
PS - I have previously posted this in http://groups.google.com/group/rhinomocks but after several days the view-count remains depressingly low.
The exception tells you exactly what is happening:
InvalidOperationException: No expectations were setup to be verified, ensure that the method call in the action is a virtual (C#) / overridable (VB.Net) method call.
Which means, in order for Rhino to properly work (or, in order for Castle to generate working proxies) your indexer has to be virtual. If you can't make it so, Rhino won't help you in this situation.
Once you make your indexer virtual, it is simple task:
var cache = MockRepository.GenerateMock<WebDataChache>();
cache.Expect(c => c["SomeKey"]).Returns("SomeValue");
// perform actual test
cache.VerifyAllExpectations();
This ensures that cache is accessed with ["SomeKey"]. If key value will be different, test will fail at VerifyAllExpectations line.

How do I check if the Create method was called using Expect instead of AssertWasNotCalled in Rhino Mocks?

How do I check if Create was not called without using the Rhino Mocks AssertWasNotCalled method.
Here is the test:
[Test]
public void When_try_to_create_directory_that_already_exits_return_false()
{
var directoryInfoMock = MockRepository.GenerateMock<IDirectoryInfoWrap>();
directoryInfoMock.Stub(x => x.Exists).Return(true);
directoryInfoMock.Expect(x => x.Create());
Assert.AreEqual(false, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoMock));
directoryInfoMock.VerifyAllExpectations();
}
Also, can someone clarify what Stub does.
directoryInfoMock.Stub(x => x.Exists).Return(true);
ensures that any call to the property directoryInfoMock.Exists will return true. But if the property is never call or called many times, it will not cause the test to fail. The purpose of the stub is to provide some meal to your code under test so that it can run normally.
directoryInfoMock.Expect(x => x.Create());
expects that the method directoryInfoMock.Create be called at least once. If not, an exception will be thrown by Rhino.Mocks during the execution of directoryInfoMock.VerifyAllExpectations().
So basically, your unit test should work as expected. What is the output of the test?
UPDATE:
You might want to specify an explicit number of times the method should be called as well. This can be done by using Repeat.x with x is Once(), Twice(), Never(), or Times(N).
directoryInfoMock.Expect(x => x.Create()).Repeat.Never();
This expects that Create is never called. And of course your test will fail if it is actually called.
If you need to make sure that only the methods you expect are called you can consider using strict mocks. Then you will get an exception when a method was called that was not expected on your mock, the only change to your code is when you create your mock:
var directoryInfoMock = MockRepository.GenerateStrictMock<IDirectoryInfoWrap>();
if you know exactly which method shouldn't be called its better to use AssertWasNotCalled (you use it after your test was executed). This way you don't tie your test with your code so closely.

How do you organise your MVC controller tests?

I'm looking for tidy suggestions on how people organise their controller tests.
For example, take the "add" functionality of my "Address" controller,
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Add()
{
var editAddress = new DTOEditAddress();
editAddress.Address = new Address();
editAddress.Countries = countryService.GetCountries();
return View("Add", editAddress);
}
[RequireRole(Role = Role.Write)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(FormCollection form)
{
// save code here
}
I might have a fixture called "when_adding_an_address", however there are two actions i need to test under this title...
I don't want to call both actions in my Act() method in my fixture, so I divide the fixture in half, but then how do I name it?
"When_adding_an_address_GET" and "When_adding_an_address_POST"?
things just seems to be getting messy, quickly.
Also, how do you deal with stateless/setupless assertions for controllers, and how do you arrange these wrt the above? for example:
[Test]
public void the_requesting_user_must_have_write_permissions_to_POST()
{
Assert.IsTrue(this.SubjectUnderTest.ActionIsProtectedByRole(c => c.Add(null), Role.Write));
}
This is custom code i know, but you should get the idea, it simply checks that a filter attribute is present on the method. The point is it doesnt require any Arrange() or Act().
Any tips welcome!
Thanks
In my opinion you should forget about naming your tests after the methods you're testing. In fact testing a single method is a strange concept. You should be testing a single thing a client will do with your code. So for example if you can hit add with a POST and a GET you should write two tests like you suggested. If you want to see what happens in a certain exceptional case you should write another test.
I usually pick names that tell a maintainer what he needs to know in Java:
#Test public void shouldRedirectToGetWhenPostingToAdd(){
//...
}
You can do this in any language and pick any *DD naming convention if you like, but the point is that the test name should convey the expectations and the scenario. You will get very small test this way and I consider this a good thing.
Well, 13 months later and no answers. Awesome.
Heres what i do now:
/tests/controllers/address/add/get.cs
/tests/controllers/address/add/valid.cs
/tests/controllers/address/add/invalid.cs