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.
Related
I have a unit test where I am using Moq and Fluent Assertions:
[Fact]
public void GetSymbols_ShouldSetSucceedToTrue_WhenSecondAttemptSucceed()
{
string selectedFileName = "testFileName.txt";
string[] expectedResult = new string[] { "testSymbol1", "testSymbol2" };
Mock<IOpenFileDialogService> mockFileDialogService = new Mock<IOpenFileDialogService>();
mockFileDialogService.SetupSequence(m => m.ShowDialog()).Returns(false).Returns(true);
mockFileDialogService.Setup(m => m.FileName).Returns(selectedFileName);
Mock<IFileService> mockFileService = new Mock<IFileService>();
mockFileService.Setup(m => m.ReadAllLines(selectedFileName)).Returns(expectedResult);
SymbolsProviderFromFile spff = new SymbolsProviderFromFile(mockFileDialogService.Object, mockFileService.Object);
// Act
spff.GetSymbols();
IEnumerable<string> result = spff.GetSymbols();
// Assert
using (new AssertionScope())
{
result.Should().Equal(expectedResult);
spff.Succeed.Should().BeTrue();
}
}
I would like to check the second call of my method.
Unfortunately when I debug this code, the spff.GetSymbols() method is only called once and it is called on the result.Should().Equals(expectedResult) line when the result is checked. There is some kind of a lazy loading here - the method is only called when the result is needed.
Why is it not called immediately in the spff.GetSymbols() line? How can I change this behavior and how can I call testing method twice in unit test?
Problem has been resolved thanks to #Dennis Doomen.
An issue about not executing method immediately was in the implementation of the spff.GetSymbols() method which uses yield return so it wasn't really related to unit testing.
I'm trying to setup unit testing for my API controllers. I'm using the mediatr pattern and FakeIteasy.
I have the following code.
public class ChannelGroupChannelsControllerTests
{
private readonly ChannelGroupChannelsController _controller;
private readonly IMediator _mediator;
public ChannelGroupChannelsControllerTests()
{
var service = A.Fake<IReadChannelGroupChannel>();
var mapper = A.Fake<IMapper>();
var channelGroupChannel = new ChannelGroupChannel
{
Id = 1,
ChannelGroupId = 1,
ChannelId = 1,
Channel = new Channel { Name = "Channel Name" }
};
_mediator = A.Fake<IMediator>();
_controller = new ChannelGroupChannelsController(_mediator, mapper);
A.CallTo(() => _mediator.Send(A<GetChannelGroupChannelById>._, A<CancellationToken>._)).Returns(channelGroupChannel);
}
[Fact]
public async Task ChannelGroupChannelsController_ById()
{
var result = await _controller.ById(1);
(result.Result as StatusCodeResult)?.StatusCode.Should().Be((int)HttpStatusCode.OK);
result.Value.Should().BeOfType<ChannelGroupChannelVM>();
}
}
Now the problem is that I keep getting NULL as a value.
I think the issue might be that GetChannelGroupChannelById has a constructor that expects the ID. But I'm not sure...
Does anybody know what could be wrong? I'm pretty new with the mocking stuff.
Kind regards
I'm not familiar with mediatr, so may be off base here, and it would be much easier to answer this question if we saw what your controller was doing. If you're able, please supply the code, as without that insight, I'm left to guess a little, but I'll try.
If GetChannelGroupChannelById's constructor expects an ID (an int?), FakeItEasy will provide an ID when it makes the Fake version. If it's an int, FakeItEasy will provide a 0, unless you've done some very fancy configuration you've not shown us. If that's supposed to line up with some other value in your code and doesn't, it may cause your problem.
Otherwise, I see you have a Fake IMapper, that is never configured, but is passed into the controller. I'm guessing this is supposed to translate some values. An unconfigured Fake will return a dummy value (or default if no dummy value can be made). It's possible that this unconfigured mapper is interrupting your flow.
(I also see that service in the test class constructor is unused. I would remove it or use it. It may not be part of your problem, but it's at least distracting.)
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 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.