How to create a stub with Moq - c#

How do I creat a pure stub using Moq? With Rhino Mocks I did it like this:
[TestFixture]
public class UrlHelperAssetExtensionsTests
{
private HttpContextBase httpContextBaseStub;
private RequestContext requestContext;
private UrlHelper urlHelper;
private string stylesheetPath = "/Assets/Stylesheets/{0}";
[SetUp]
public void SetUp()
{
httpContextBaseStub = MockRepository.GenerateStub<HttpContextBase>();
requestContext = new RequestContext(httpContextBaseStub, new RouteData());
urlHelper = new UrlHelper(requestContext);
}
[Test]
public void PbeStylesheet_should_return_correct_path_of_stylesheet()
{
// Arrange
string expected = stylesheetPath.FormatWith("stylesheet.css");
// Act
string actual = urlHelper.PbeStylesheet();
// Assert
Assert.AreEqual(expected, actual);
}
}
How would I create a stub for MockRepository.GenerateStub<HttpContextBase>(); using Moq? Or should I just stay with Rhino Mocks?

Here is my suggestion for you:
Mock<HttpContextBase> mock = new Mock<HttpContextBase>();
mock.SetupAllProperties();
Then you have to do the setup.
For further informations see homepage of the MOQ project.

A bit late to the party here but there's still not a sufficient answer here in my opinion.
Moq doesn't have explicit stub and mock generation in the same way RhinoMocks does. Instead, all setup calls, e.g. mockObject.Setup(x => blah ...) create a stub.
However, if you want the same code be treated as a mock, you need to call mockObject.Verify(x => blah ...) to assert that the setup ran as you expected.
If you call mockObject.VerifyAll(), it will treat everything you have setup as mocks and this is unlikely to be the behaviour you wish, i.e. all stubs treated as mocks.
Instead, when setting up the mock use the mockObject.Setup(x => blah ...).Verifiable() method to mark the setup explicitly as a mock. Then call mockObject.Verify() - this then only asserts the setups that have been marked with Verifiable().

var mockHttpContext = new Mock<HttpContextBase>();

Related

dotnet core web app unit test controller

I have a dotnetcore web app and am looking to unit test the controllers. How do I get about this?
I have a simple controller that looks like this
public class ConversionController : Controller {
private readonly INumberService _numberService;
public ConversionController(INumberService numberService)
{
this._numberService = numberService;
}
// GET http://localhost:9789/api/conversion/123
[HttpGet("{number}")]
public string Get(decimal number)
{
return _numberService.ConvertToWords(number);
}
}
The INumberService is passed in as a parameter. How do I unit test this?
By mocking the interface/dependency and exercising an isolated unit test for the Get method. You could either create your own mock or use a mocking framework to mock the dependency. From there assert that the system under test behaves as expected.
For example the following simple test uses Moq to mock the dependency and test the Get method.
[TestMethod]
public void ConversionController_Get_Should_Return_Five() {
//Arrange
var number = 5;
var expected = "five";
var mock = new Mock<INumberService>();
mock.Setup(_ => _.ConvertToWords(number)).Returns(expected);
var sut = new ConversionController(mock.Object);
//Act
var actual = sut.Get(number);
//Assert
Assert.AreEqual(expected, actual);
}
You should also take some time and check the documentation provided
Unit Testing in .NET Core

HttpContext Null through Unit testing

I have following piece of code to evaluate the IP address
public string getIPAddress()
{
string IPAddress = string.Empty;
String strHostName = HttpContext.Current.Request.UserHostAddress.ToString();
IPAddress = System.Net.Dns.GetHostAddresses(strHostName).GetValue(0).ToString();
return IPAddress;
}
Now when I tried to implement unit testing for this method, it always throws error, null reference,
I could not change the actual method just for unit testing, is there any way to handle this...
Thanks
That is expected because HttpContext is not available in unit tests and unit tests run in their own context. You will need to have a way to mock/provide HttpContext to your unit tests.
if you would not use "HttpContext.Current.Request.UserHostAddress" direct - but through a wrapperclass or other mockable class instead, you could then mock the behaviour.
Here is an Example
you should probably mock System.Net.Dns.GetHostAddresses(strHostName).GetValue(0) as well, to get your Test independent of this Class too.
if you want to mock HTTPContext while unit testing you can use typemock as in the following example regarding you method:
[TestMethod,Isolated]
public void TestForHttpContext_willReturn123AsIP()
{
// Arrange
Program classUnderTest = new Program();
IPAddress[] a = { new IPAddress(long.Parse("123")), new IPAddress(long.Parse("456")), new IPAddress(long.Parse("789")) };
Isolate.WhenCalled(() => HttpContext.Current.Request.UserHostAddress).WillReturn("testIP");
Isolate.WhenCalled(() => Dns.GetHostAddresses(" ")).WillReturn(a);
// Act
var res = classUnderTest.getIPAddress();
// Assert
Assert.AreEqual("123.0.0.0", res);
}

Correctly implement Unit Test

I'm practicing on writing unit tests for the first time, and I have some questions. I'll start of by explaining what I'm trying to test.
I would like to test a method which looks like this:
public bool IsAdmin(HubCallerContext hubCallerContext)
{
return hubCallerContext.User.IsInRole("admin");
}
The method is implemented in a class UserService, which is connected to a interface IUserService.
I'm trying to create 2 tests:
One with a HubCallerContext which is in the role of "admin" and will assert true.
One with a HubCallerContext which is in the role of "user" and will assert false.
I've created a new class library in my solution, where I've refrenced the project I'm testing. I've installed NUnit and Moq, and created a test class which looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChatProj;
using NUnit.Framework;
using ChatProj.Controllers;
using Moq;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using ChatProj.DAL;
using ChatProj.Service_Layer;
using System.Threading.Tasks;
namespace ChatProj.Tests
{
[TestFixture]
public class Class1
{
[SetUp]
public void Setup()
{
}
[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService userService = new UserService();
bool result = userService.IsAdmin( ? );
Assert.IsTrue( result, "Something is wrong." );
}
[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
UserService userService = new UserService();
bool result = userService.IsAdmin( ? );
Assert.IsFalse( result, "Something is wrong." );
}
}
}
Here I start to get confused. (I've marked the parameters of the IsAdmin calls with "?" because I'm not sure what to put there.)
I've read about mocks, stubs, fakes and dummies, but the definitions are to abstract for me to really grasp. I've found these definitions for example:
- Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
- Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
- Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
- Mocks are objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
As I've designed my test class, I would need some sort of substitution for my HubCallerContext. This is assuming I'm testing the "IsAdmin" method the right way.
So my questions are:
Am I testing the "IsAdmin" method in a good way?
How would I practically make the tests work? Do I use a mock, and in that case, could you show how I would implement that, or point me in the right direction? Here is how the HubCallerContext works for
refrence.
Assuming HubCallerContext is this one - https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Core/Hubs/HubCallerContext.cs - then setting up the tests will be easy. You just want two mocks of IPrincipal, one of which returns true for the .IsInRole("admin") call and the other that returns false.wrap these two in mocks of IRequest.
The syntax will vary depending on the mocking framework used, but your tests will end up something like:
[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService userService = new UserService();
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
var requestMock = new Mock<IRequest>();
requestMock.Setup(x => x.User).Returns(principalMock.Object);
var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
Assert.IsTrue( result, "Something is wrong." );
}
[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
UserService userService = new UserService();
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
var requestMock = new Mock<IRequest>();
requestMock.Setup(x => x.User).Returns(principalMock.Object);
var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
Assert.IsFalse( result, "Something is wrong." );
}
I haven't checked if the above compiles, but it is based on the syntax needed for Moq.
I think that it would be much easier for You to write these two unit tests if You would change the method under test a little (assuming it's not a part of legacy code).
If you define the method this way:
public bool IsAdmin(IPrincipal user)
{
return user.IsInRole("admin");
}
things would get pretty simple (btw. check the "Law of Demeter" ;)). You can pass in a mock object (since the user parameter is an interface - IPrincipal) returning true if the user should be in role "admin" and false otherwise.
The benefit of this solution is that You don't have to build a graph of mock objects and the arrange part of your test is pretty simple. Your tests could look somewhat like this:
[Test]
public void IsAdmin_CalledByAdminUser_ReturnTrue()
{
//Arrange
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
//Act
var userService = ...// create an instance of userService here
var result = userService.IsAdmin(principalMock);
//Assert
Assert.IsTrue(result);
}
[Test]
public void IsAdmin_CalledByNonAdminUser_ReturnFalse()
{
//Arrange
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
//Act
var userService = ...// create an instance of userService here
var result = userService.IsAdmin(principalMock);
//Assert
Assert.IsFalse(result);
}
I would recommend You to read this series of blog posts (I think it's pretty cool :)): http://www.daedtech.com/tag/unit-testing
You can get the list of roles and check for each roles using foreach.

AutoFixture as an Automocking container vs Automocking differences?

I started to use moq but from my understanding I always have to mock up all the methods that could be called even if I really do not care about them.
Sometimes it takes so long to mockup stuff you forget what you want to do. So I been looking at auto mocking but I am not sure what one I should use.
AutoFixture as an auto-mocking container
Automocking
I don't get how to use the first one at all. I sort of get the second one but never really tried it.
I am not sure if one is better than the other. The only thing I know is I am using AutoFixtures already what is a dependency of the first one.
So maybe in the long run it makes sense to go with the first one but like I said I can't find any basic tutorials on how to use it.
Edit
I am trying to follow "Nikos Baxevanis" examples but I am running into errors.
Failure: System.ArgumentException : A matching constructor for the given arguments was not found on the mocked type.
----> System.MissingMethodException : Constructor on type 'DatabaseProxyded46c36c8524889972231ef23659a72' not found.
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var fooMock = fixture.Freeze<Mock<IFoo>>();
// fooMock.Setup(x => x.GetAccounts(It.IsAny<IUnitOfWork>()));
var sut = fixture.CreateAnonymous<AdminService>();
sut.Apply();
fooMock.VerifyAll();
I think it is because of my petapoco unitOfWork property
PetaPoco.Database Db { get; }
Not sure if I got to mock this up somehow or what.
While I have never used moq-contrib Automocking, I could probably provide some information on using AutoFixture as an auto-mocking container.
Currently there is support for Moq, Rhino Mocks, FakeItEasy, and NSubstitute. Just install the appropriate extension AutoMoq, AutoRhinoMocks, AutoFakeItEasy, and AutoNSubstitute.
Once you have installed one of the extensions for Auto Mocking the extra call is:
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
(or if you are using Rhino Mocks)
var fixture = new Fixture()
.Customize(new AutoRhinoMockCustomization());
(or if you are using FakeItEasy)
var fixture = new Fixture()
.Customize(new AutoFakeItEasyCustomization());
(or if you are using NSubstitute)
var fixture = new Fixture()
.Customize(new AutoNSubstituteCustomization());
Example 1
public class MyController : IController
{
public MyController(IFoo foo)
{
}
}
public interface IFoo
{
}
Here is how to use AutoFixture to create instances of MyController class:
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
var sut = fixture.CreateAnonymous<MyController>();
Now, if you inspect the sut variable you will see the the IFoo is a mocked instance (having a type name similar to Castle.Proxies.IFooProxy).
Example 2
This examples extends the previous one.
You can instruct AutoFixture to use your own, pre-configured, mocked instance:
var fooMock = fixture.Freeze<Mock<IFoo>>();
// At this point you may setup expectation(s) on the fooMock.
var sut = fixture.CreateAnonymous<MyController>();
// This instance now uses the already created fooMock.
// Verify any expectation(s).
That's basically it - but it can go further!
Below are the previous examples using AutoFixture decleratively with the xUnit.net extension.
Example 1
[Theory, AutoMoqData]
public void TestMethod(MyController sut)
{
// Start using the sut instance directly.
}
Example 2
[Theory, AutoMoqData]
public void TestMethod([Frozen]Mock<IFoo> fooMock, MyController sut)
{
// At this point you may setup expectation(s) on the fooMock.
// The sut instance now uses the already created fooMock.
// Verify any expectation(s).
}
You may find more information on this blog post which contains links to everything related around AutoFixture, xUnit.net, and Auto Mocking.
Hope that helps.

Unit Testing an Html Helper with AutoFixture

I'm attempting to Unit Test an Html Helper using AutoFixture. Below is my SUT
public static MvcHtmlString SampleTable(this HtmlHelper helper,
SampleModel model, IDictionary<string, object> htmlAttributes)
{
if (helper == null)
{
throw new ArgumentNullException("helper");
}
if (model == null)
{
throw new ArgumentNullException("model");
}
TagBuilder tagBuilder = new TagBuilder("table");
tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.GenerateId(helper.ViewContext.HttpContext.Items[Keys.SomeKey].ToString());
return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
}
As you can see it just returns an MVC Html string with table tags and Id attached to it. (See below Unit Test result for an example)
Unit Test with AutoFixture:
[Fact]
public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()
{
var fixture = new Fixture();
//Arrange
fixture.Inject<HttpContextBase>(new FakeHttpContext());
var httpContext = fixture.CreateAnonymous<HttpContextBase>();
fixture.Inject<ViewContext>(new ViewContext());
var vc = fixture.CreateAnonymous<ViewContext>();
vc.HttpContext = httpContext;
vc.HttpContext.Items.Add(Keys.SomeKey, "foo");
fixture.Inject<IViewDataContainer>(new FakeViewDataContainer());
var htmlHelper = fixture.CreateAnonymous<HtmlHelper>();
var sampleModel = fixture.CreateAnonymous<SampleModel>();
//Act
var result = SampleHelpers.SampleTable(htmlHelper, sampleModel, null).ToString();
//Assert
Assert.Equal("<table id=\"foo\"></table>", result);
}
FakeHttpContext and FakeViewDataContainer are just the fake implementations of HttpContextBase and IViewDataContainer.
This test passes and returns the expected result. However, I ‘m not sure I’m correctly utilizing the Autofixture here. Is there a better way to use AutoFixture within this Unit Test?
Based on partial information it's hard to tell exactly how the above test could be further reduced, but I would guess that it could be reduced.
First of all, the combo of invoking Inject followed by CreateAnonymous is rather idiomatic - particularly if you reverse the sequence. This is called Freezing the anonymous value (and is equivalent to a DI container's Singleton lifetime scope). It can be stated more succinctly like this:
var vc = fixture.Freeze<ViewContext>();
It also seems as though the test is mapping HttpContext to FakeHttpContext. Mapping can be done a little bit easier, but that'll map Transient instances...
In any case, unless you have compelling reasons to use Manual Mocks instead of a dynamic Mock library, you might as well decide to use AutoFixture as an auto-mocking container. That might rid you of a lot of that type mapping.
So, given all that, I'd guess that you might be able to reduce the test to something like this:
[Fact]
public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
//Arrange
var vc = fixture.Freeze<ViewContext>();
vc.HttpContext.Items.Add(Keys.SomeKey, "foo");
var htmlHelper = fixture.CreateAnonymous<HtmlHelper>();
var sampleModel = fixture.CreateAnonymous<SampleModel>();
//Act
var result = SampleHelpers.SampleTable(htmlHelper, sampleModel, null).ToString();
//Assert
Assert.Equal("<table id=\"foo\"></table>", result);
}
However, most of the Arrange part is now purely declarative, and since you seem to already be using xUnit.net, you can use AutoData Theories for AutoFixture to move most of the variables to method arguments:
[Theory, AutoMoqData]
public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml(
[Frozen]ViewContext vc,
HtmlHelper htmlHelper,
SampleModel sampleModel)
{
//Arrange
vc.HttpContext.Items.Add(Keys.SomeKey, "foo");
//Act
var result = SampleHelpers.SampleTable(htmlHelper, sampleModel, null).ToString();
//Assert
Assert.Equal("<table id=\"foo\"></table>", result);
}
This assumes that you've bridged the AutoMoqCustomization with the AutoDataAttribute like this:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute :
base(new Fixture().Customize(new AutoMoqCustomization()))
{ }
}
Please keep in mind that you may need to tweak the above code a bit to make it fit the details of your API. This is only meant as a sketch.

Categories

Resources