I'm trying to work out why some of my test cases (using RhinoMocks 3.6 Build 20) aren't working, and I've narrowed the issue down to the following minimal unit test:
public interface ITest
{
string Something { get; }
}
[Test]
public void TestStub()
{
var mockery = new MockRepository();
var testItem = mockery.Stub<ITest>();
testItem.Stub(x => x.Something).Return("Hello");
Assert.AreEqual("Hello", testItem.Something);
}
This fails with the message:
Expected: "Hello" But was: null
Any ideas what I'm doing wrong here? I've found a few examples on SO and the Rhino Wiki on how to stub read-only properties, and as far as I can tell, this should work fine.
Cheers in advance.
EDIT: Based on sll's advice below, I tried replacing
testItem.Stub(x => x.Something).Return("Hello");
with
testItem.Expect(x => x.Something).Return("Hello");
and the test still fails in the same manner.
Edit 2: I've got this working by adding the line
mockery.ReplayAll();
before the Assert - but I thought this was no longer required (from the wiki: "Mocks/stubs returned from MockRepository.GenerateMock() and MockRepository.GenerateStub() are returned in replay mode, and do not require explicit move to replay mode.")
Try out generating Mock instead:
var testItem = MockRepository.GenerateMock<ITest>();
testItem.Expect(x => x.Something).Return("Hello");
Assert.AreEqual("Hello", testItem.Something);
Als make sure you shared entire test method, perhaps you ignored some lines of code?
Try out usign Repeat.Any() perhaps proeprty accessed before you are doing expectation.
testItem.Expect(x => x.Something).Return("Hello").Repeat.Any();
On example page Stub() used for methods, and suggested using Mock's Expect() for properties:
Using Expect() to set up properties
The Expect() extention method can be used to set up expectations and
return values for properties.
Got it:
From the RhinoMocks 3.6 Blog Post comments:
09/03/2009 05:34 PM by
Kurt Harriger
FYI,
I had a few dozen tests fail after upgrading to v 3.6 from code like this:
var mocks = new MockRepository();
var something = mocks.Stub
something.Stub(x=>x.DoSomething() ).Return(true);
something.DoSomething();
The root cause of the problem appears that mock.Stub/Mock/etc no longer returns the mock in replay mode. To fix replaced mock.Stub with MockRepository.GenerateStub.
Ayende Rahien
09/03/2009 06:50 PM by
Ayende Rahien
Kurt,
That is actually expected, that should have never worked
So, by changing the test to:
[Test]
public void TestStub()
{
var testItem = MockRepository.GenerateStub<ITest>();
testItem.Stub(x => x.Something).Return("Hello");
Assert.AreEqual("Hello", testItem.Something);
}
this now works.
Cheers
You are just setting the value so you would expect to do this like this:
public interface ITest
{
string Something { get; }
}
[Test]
public void TestStub()
{
var mockery = new MockRepository();
var testItem = mockery.Stub<ITest>();
testItem.Something = "Hello";
Assert.AreEqual("Hello", testItem.Something);
}
No need to Stub with Func.
Related
In Moq, I want to assert that a method TestMethod is called with a specific parameter. When the test fails, I want to see a useful error message similar to:
TestMethod called with unexpected value X for parameter P where Y expected.
public interface ITestObject
{
void TestMethod(int parameter);
}
Just for sake of illustration, I could achieve this using a handcoded mock as follows:
Assert.AreEqual failed. Expected:<3>. Actual:<2>. TestMethod called with unexpected value for parameter 'actual'.
public class MockTestMethodParameter : ITestObject
{
private readonly int expected;
public MockTestMethodParameter(int expected) { this.expected = expected; }
public void TestMethod(int actual)
{
Assert.AreEqual(actual, expected, $"{nameof(TestMethod)} called with unexpected value for parameter '{nameof(actual)}'.");
}
}
[TestMethod]
public void TestHandcodedMockFailure()
{
var mock = new MockTestMethodParameter(expected: 2);
mock.TestMethod(actual: 3);
}
My problem is, I can't figure out how to do this in Moq. When I set up my Mock and call Verify(), I get the following unexpected and unclear error message, instead of the message I was hoping for:
Expected invocation on the mock at least once, but was never performed: test => test.TestMethod(It.Is(2, GenericEqualityComparer))
Performed invocations:
MockUnitTest1.ITestObject:1 (test):
UnitTest1.ITestObject.TestMethod(3)
[TestMethod]
public void TestMoqFailure()
{
var expected = 2;
var actual = 3;
var mock = new Moq.Mock<ITestObject>(Moq.MockBehavior.Strict);
mock.Setup(test => test.TestMethod(Moq.It.IsAny<int>())).Verifiable();
mock.Object.TestMethod(actual);
mock.Verify(test => test.TestMethod(Moq.It.Is(expected, EqualityComparer<int>.Default)));
}
Granted, the information is there, but I expected something more along the lines of, "TestMethod was invoked, but with incorrect parameters." It confuses me when Moq reports that TestMethod was not invoked because, intuitively, I did invoke the mock. I called TestMethod with It.IsAny(), as declared in the mock setup.
I've tried many different adjustments, but none yielding the desired result:
Custom error message
Setup with Is(3)
Setup with Is(2)
MockBehavior.Loose
Different .NET platforms, Framework 4.6.1, Core 2.1, .NET 6.0
Is this simply the way Moq reports error results for Verify()? I'm new to Moq, and while this behavior is unexpected to me, perhaps it is working as designed.
This appears to be normal behavior for mock frameworks in general. Doing the same thing with Telerik JustMock yields a similar error message:
Occurrence expectation failed. Expected exactly 1 call. Calls so far: 0
[TestMethod]
public void TestJustMockFailure()
{
var expected = 2;
var actual = 3;
var mock = Mock.Create<ITestObject>(Behavior.Strict);
Mock.Arrange(() => mock.TestMethod(Arg.IsAny<int>()));
mock.TestMethod(actual);
Mock.Assert(() => mock.TestMethod(Arg.Is(expected)), Occurs.Once());
}
In summary:
The OP's use case (my use case) is valid, verifying a particular parameter value was passed to a mocked method. However, the error message does not report the parameter mismatch as such. Rather, it reports that the entire mocked method call did not occur. This is by design, and appears to be common among popular mock frameworks.
Coming from using Moq, I'm used to being able to Setup mocks as Verifiable. As you know, this is handy when you want to ensure your code under test actually called a method on a dependency.
e.g. in Moq:
// Set up the Moq mock to be verified
mockDependency.Setup(x => x.SomethingImportantToKnow()).Verifiable("Darn, this did not get called.");
target = new ClassUnderTest(mockDependency);
// Act on the object under test, using the mock dependency
target.DoThingsThatShouldUseTheDependency();
// Verify the mock was called.
mockDependency.Verify();
I've been using VS2012's "Fakes Framework" (for lack of knowing a better name for it), which is quite slick and I'm starting to prefer it to Moq, as it seems a bit more expressive and makes Shims easy. However, I can't figure out how to reproduce behavior similar to Moq's Verifiable/Verify implementation. I found the InstanceObserver property on the Stubs, which sounds like it might be what I want, but there's no documentation as of 9/4/12, and I'm not clear how to use it, if it's even the right thing.
Can anyone point me in the right direction on doing something like Moq Verifiable/Verify with VS2012's Fakes?
-- 9/5/12 Edit --
I realized a solution to the problem, but I'd still like to know if there's a built-in way to do it with VS2012 Fakes. I'll leave this open a little while for someone to claim if they can. Here's the basic idea I have (apologies if it doesn't compile).
[TestClass]
public class ClassUnderTestTests
{
private class Arrangements
{
public ClassUnderTest Target;
public bool SomethingImportantToKnowWasCalled = false; // Create a flag!
public Arrangements()
{
var mockDependency = new Fakes.StubIDependency // Fakes sweetness.
{
SomethingImportantToKnow = () => { SomethingImportantToKnowWasCalled = true; } // Set the flag!
}
Target = new ClassUnderTest(mockDependency);
}
}
[TestMethod]
public void DoThingThatShouldUseTheDependency_Condition_Result()
{
// arrange
var arrangements = new Arrangements();
// act
arrangements.Target.DoThingThatShouldUseTheDependency();
// assert
Assert.IsTrue(arrangements.SomethingImportantToKnowWasCalled); // Voila!
}
}
-- 9/5/12 End edit --
Since I've heard no better solutions, I'm calling the edits from 9/5/12 the best approach for now.
EDIT
Found the magic article that describes best practices. http://www.peterprovost.org/blog/2012/11/29/visual-studio-2012-fakes-part-3/
Although it might make sense in complex scenarios, you don't have to use a separate (Arrangements) class to store information about methods being called. Here is a simpler way of verifying that a method was called with Fakes, which stores the information in a local variable instead of a field of a separate class. Like your example it implies that ClassUnderTest calls a method of the IDependency interface.
[TestMethod]
public void DoThingThatShouldUseTheDependency_Condition_Result()
{
// arrange
bool dependencyCalled = false;
var dependency = new Fakes.StubIDependency()
{
DoStuff = () => dependencyCalled = true;
}
var target = new ClassUnderTest(dependency);
// act
target.DoStuff();
// assert
Assert.IsTrue(dependencyCalled);
}
I've just began to work with Rhino-Mock, and I would like to test a basic method who check if pseudo and password is not null...
Here is my test method:
public void ValidateLoginTest()
{
// Arrange
var stubConnectionToTfs = MockRepository.GenerateStub<IConnectionToTfs>();
stubConnectionToTfs.Expect(x => x.ValidateLogin()).Return(false);
stubConnectionToTfs.Pseudo = "testPseudo";
stubConnectionToTfs.Password = "testPasswordl";
stubConnectionToTfs.Expect(x => x.ValidateLogin()).Return(true);
// Act
// Assert
stubConnectionToTfs.VerifyAllExpectations();
}
Maybe I didn't understand howrhino-mock works but I tought that if I called my ValidateLogin method without setting my Pseudo and Password properties, and then call VerifyAllExpectations() it will be enough to test my method...
The thing is, if I comment my Setters, the test pass anyway...
Thanks in advance
if you want to set expectancies you have to use a Mock, not a stub.
I'm trying to become more familiar with the Rhinomocks framework, and I'm trying to understand the Expect methods of rhinomocks.
Here's a unit test I have written:
[TestMethod]
public void Create_ValidModelData_CreatesNewEventObjectWithGivenSlugId()
{
//Arrange
var eventList = new List<Event>() { new Event() { Slug = "test-user" } };
_stubbedEventRepository.Stub(x => x.GetEvents())
.Return(eventList);
_stubbedEventRepository
.Expect(x => x.SaveEvent(eventList.SingleOrDefault()))
.Repeat
.Once();
var controller = new EventController(_stubbedEventRepository);
EventViewModel model = new EventViewModel();
//Act
//controller.Create(model); COMMENTED OUT
//Assert
_stubbedEventRepository.VerifyAllExpectations();
}
I thought I understood this code to only pass if the SaveEvent(...) method get's called exactly once. However, with controller.Create(model) commented out, the test still passes. Inside controller.Create(model) is where the SaveEvent() method gets called.
I tried the following:
_stubbedEventRepository
.Expect(x => x.SaveEvent(eventList.SingleOrDefault()));
But it still passes every time, so what am I doing incorrectly stack overflow? The sources I have looked at online haven't been able to help me. Why is VerifyAllExpectations() yielding a successful unit test?
Thank you!
Here's the body of the controller constructor:
public EventController(IEventRepository eventRepository)
{
_eventRepository = eventRepository;
}
edit:
// member variables
private IEventRepository _stubbedEventRepository;
[TestInitialize]
public void SetupTests()
{
_stubbedEventRepository = MockRepository.GenerateStub<IEventRepository>();
}
If you want to verify the behavior of the code under test, you will use a mock with the appropriate expectation, and verify that. If you want just to pass a value that may need to act in a certain way, but isn't the focus of this test, you will use a stub.
Following the directions at: http://www.telerik.com/help/justmock/advanced-usage-static-mocking.html
I'm unsuccessful in mocking ConfigurationManager.AppSettings. Here's the code I'm using...
[TestMethod]
public void my_test()
{
// Arrange
var appSettings = new NameValueCollection {
{ "test1", "one" }
};
Mock.Arrange(() => ConfigurationManager.AppSettings)
.Returns(appSettings)
.MustBeCalled();
// Act
var test1 = ConfigurationManager.AppSettings["test1"];
// Assert
Assert.AreEqual("one", test1);
}
This is the error I receive.
Assert.AreEqual failed. Expected:. Actual:<(null)>.
Is it possible to mock this object?
[edit] I'm also using the Trial.
I just tried your test and it worked as expected:
// Arrange
var appSettings = new NameValueCollection { { "test1", "one" } };
Mock.Arrange(() => ConfigurationManager.AppSettings)
.Returns(appSettings)
.MustBeCalled();
// Act
var test1 = ConfigurationManager.AppSettings["test1"];
// Assert
Assert.AreEqual("one", test1);
Here please make sure that Configuration.AppSettings is not already invoked in some static constructor of your project.
Here to note that .net profiler intercepts during OnJITCompilationStarted and this fires only once for a given member.
Moreover, please make sure that your profiler is configured properly and JM plugin for VS is installed. You can check if the profiler is enabled by Mock.IsProfilerEnabled.
Finally, you generally dont need to use Mock.SetupStatic(#TARGET_TYPE#), unless you are doing strict mock or want to fake static constructor for a given type. When you will be doing Mock.Arrange, it will automatically set the interceptors if not already.
[Note: I used the latest version]
source: http://www.telerik.com/community/forums/justmock/general-discussions/problems-mocking-the-configurationmanager-appsettings.aspx
Official response is, this appears to be an issue with MSTest only.