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

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.

Related

How can I use mockito to verify that a function has never been called, with any argument?

I want to verify that a function has never been called using mockito. I am aware of the verifyNever function, but that does not seem to work in my case, or I'm not using it correctly.
My test currently looks like this:
test('when the string is less than 3 characters api is not called', () async {
var databaseService = getAndRegisterDatabaseService();
var model = ViewModel();
model.searchPatient('sk');
// Wait for futures to finish.
await Future.delayed(Duration(seconds: 0));
verifyNever(databaseService.searchPatient('sk'));
});
but I get an error when running the test:
No matching calls (actually, no calls at all).
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)
To me it seems like verifyNever won't work if the function has never been called, just that it has never been called with a specific argument. Is that correct? In that case, is there another way to test what I want?
The verifyNever examples from package:mockito's README.md cover your case:
// Or never called
verifyNever(cat.eatFood(any));
So, in your case, assuming that databaseService is a Mock object, you should be able to use verifyNever(databaseService.searchPatient(any)); to verify that the .searchPatient method is never called, regardless of the arguments.
After trying to write a minimal reproducible example it turns out that the problem was that I read the output incorrectly.
In the following output I read the top row as the title for the failed test, when in fact it is the bottom row that is the name of the failed error than corresponds to the above output.
✓ ViewmodelTest - searchPatient - when the string is less than 3 characters api is not called
No matching calls (actually, no calls at all).
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)
package:test_api fail
_VerifyCall._checkWith
package:mockito/src/mock.dart:672
_makeVerify.<fn>
package:mockito/src/mock.dart:954
main.<fn>.<fn>.<fn>
test/viewmodel_tests/viewmodel_test.dart:144
✖ ViewmodelTest - searchPatient - api is called with correct and cleaned query

Tweaking an output before testing using MRUnit

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.

How to assert a fake object's method was called more than once using a different param for each call using FakeItEasy?

I am currently using FakeItEasy for unit testing. I'm faking NServiceBus .Send method call was made in a method.
The problem I'm running across is I'm sending out two message on the bus in the method:
bus.Send(new CommandOne(Id = [something]));
bus.Send(new CommandTwo(Id = [something]));
both commands are sent on the faked bus in the same method call (I removed the real command names and params for the sake of simplicity).
Here is what my NUnit code/FakeItEasy code looks like:
bus = A.Fake<IBus>;
var sut = new Sut(bus);
sut.MethodCall();
A.CallTo(() => bus.Send(A<CommandOne>.That.Matches(co => co.Id == [someId]).MustHaveHappened(Repeated.Exactly.Once);
A.CallTo(() => bus.Send(A<CommandTwo>.That.Matches(co => co.Id == [someId]).MustHaveHappened(Repeated.Exactly.Once);
But, when I run this test, I get a test failed result, stating:
System.InvalidCastException : Unable to cast object of type 'CommandTwo' to type 'CommandOne'.
When I send two different commands suing the same fake, I'm specifying the specific object type and a match on the properties of the command, but FakeItEasy is trying to cast the first command being sent (CommandOne), two the second command sent (CommandTwo)...
is there a way to use FakeItEasy to test the same method being called twice of a faked object with different values for each call?
Thanks,
Mike
Your problem sounds very much like Issue 326 - Argument Constraints should support derived types as Type Arguments, which was recently fixed in FakeItEasy release 1.22.0. If you're not using that release, please upgrade and see if the behaviour persists.
If you are using 1.22.0, please come back and comment so we can keep trying!

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 assert a generic method was called with Rhino Mocks?

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>());
}