I am trying to unit test using Moq. Here is the example code:
public class ConcreteClass
{
private readonly FirstPropery firstProperty;
private readonly SecondProperty secondProperty;
public ConcreteClass(firstProperty, secondProperty)
{
this.firstProperty = firstProperty;
this.secondProperty = secondProperty;
}
}
[TestMethod]
var concreteClassMock = new Mock<ConcreteClass>() { CallBase = true };
In my test method, I want to set firstProperty to reference a real object FirstProperty object (created by a factory), and later use it to test another object's behavior. Is there any way to achieve that?
Usually, you wouldn’t mock private members since you are only mocking the public interface of something. A mock is thus completely independent of implementation details.
That being said, you can pass constructor arguments to the Mock constructor that will then be passed on to the target’s constructor:
new Mock<ConcreteClass>(firstProperty, secondProperty) {CallBase = true};
However, if your goal is to actually test the ConcreteClass, you should not create a mock of it. You should test the actual object. So mock its dependencies and pass those if necessary, but keep the object you want to test actually real. Otherwise, you might introduce and test behavior that comes from the mock instead of the object you are testing:
var firstMock = new Mock<FirstProperty>();
var secondMock = new Mock<FirstProperty>();
var obj = new ConcreteClass(firstMock.Object, secondMock.Object);
obj.DoSomething();
// assert stuff
A few remarks:
1- It could be easily achieve with an interface and a get method like this:
public interface IConcreteClass
{
FirstProperty FirstProperty { get; }
}
[Test]
public void TestCase()
{
var yourFirstPropertyImplementation = new FirstProperty();
var concreteClassMock = new Mock<IConcreteClass>();
concreteClassMock.Setup(o => o.FirstProperty).Returns(yourFirstPropertyImplementation);
}
2- Depending of your scenario, do you really need a Moq, why not just use the true implementation and use moq only at boundaries?
3- You should clarify what you want to test? If it's concrete class? or the properties? or some other classes? The test case I propose in 1 is valid only to test the interaction of concrete class with some other classes.
Related
I have a User Interface lets call it IUser.
There are two implementations of this: AdminUser and NormalUser.
Now, I am trying to use these user classes via Unit Testing(Mocking).
I mock the interface as follows:
var mockUser = new Mock<IUser>();
mockUser.get("username");
I have added breakkpoints throughout the classes but I am not sure which instance of the interface is getting called i.e AdminUser or NormalUser.
It never stops at the debug points and no clue from the mockUser instance.
How can I get the details of the class being called by the mockUser mock instance?
Thanks in advance.
Creating a Mock<IUser> actually creates a new implementation of IUser. So it won't help you to test any of your actual implementations.
Using a Mock works something like this:
Suppose I have this class and interface. The class validates whether a postal code is valid for a country. It depends on another interface which provides the regex pattern for the given country.
public class PostalCodeValidator
{
private readonly IPostalCodeRegexProvider _regexProvider;
public PostalCodeValidator(IPostalCodeRegexProvider regexProvider)
{
_regexProvider = regexProvider;
}
public bool ValidatePostalCode(string postalCode, string countryCode)
{
var regex = _regexProvider.GetPostalCodeRegex(countryCode);
if (string.IsNullOrEmpty(regex)) return true;
return Regex.IsMatch(postalCode, regex);
}
}
public interface IPostalCodeRegexProvider
{
string GetPostalCodeRegex(string countryCode);
}
The implementation of IPostalCodeRegexProvider could be anything. It could call a database, it could be hard-coded.
But when I write unit tests for PostalCodeValidator, I explicitly don't want to test a real implementation of IPostalCodeRegexProvider. I want to make IPostalCodeValidator return exactly what I want so that I can make sure that PostalCodeValidator works. I'm only testing PostalCodeValidator.
If I want to test that ValidatePostalCode returns true when IPostalCodeRegexProvider.GetPostalCode returns null, then I need to make sure that it will return null. That's where the Mock comes in.
It allows me to easily create an implementation of IPostalCodeRegexProvider that will always return null, so I can test what ValidatePostalCode does with that null.
[TestMethod]
public void ValidatePostalCode_ReturnsTrueWhenRegexIsNull()
{
var mock = new Mock<IPostalCodeRegexProvider>();
mock.Setup(x => x.GetPostalCodeRegex(It.IsAny<string>())).Returns(default(string));
var subject = new PostalCodeValidator(mock.Object);
Assert.IsTrue(subject.ValidatePostalCode("xyz","abc"));
}
Whatever the subject of the test is - in this case PostalCodeValidator, or in your case AdminUser and NormalUser - that's what you would create an instance of. If those classes depend on other interfaces then you might create a Mock for each of those interfaces.
You can also consider using a "test double." Instead of using Moq, you just create a simple class that implements the interface. For example, what I did with Moq I could also do like this:
public class PostalCodeRegexProviderThatReturnsNull : IPostalCodeRegexProvider
{
public string GetPostalCodeRegex(string countryCode)
{
return null;
}
}
Now the unit test would look like this:
public void ValidatePostalCode_ReturnsTrueWhenRegexIsNull()
{
var regexProvider = new PostalCodeRegexProviderThatReturnsNull();
var subject = new PostalCodeValidator(regexProvider);
Assert.IsTrue(subject.ValidatePostalCode("xyz","abc"));
}
That is often easier to understand than using a Mock. Sometimes the setup for mocks can get complicated and difficult to read and debug, but a simple class can do the job just as well or even better.
In order to test the actual implementations then you need to initialize the actual implementations i.e. new AdminUser().
For example
[TestMethod]
public void TestAdminUser {
//Arrange
IUser admin = new AdminUser();
//...set any necessary members relevant to the test
//Act
//...invoke member to be tested
//Assert
//...verify actual to expected behavior
}
If either of the implementations have external dependencies then you would mock those (the dependencies) and inject them.
If a class depended on an IUser
public class SomeClass {
private readonly IUser user;
public SomeClass(IUser user) {
this.user = user;
}
//...
}
and you wanted to test that class then you would have a reason to mock IUser for an isolated unit test.
[TestMethod]
public void TestSomeClass {
//Arrange
var username = "dummy";
var expected = "some value";
var mock = new Mock<IUser>();
//...set any necessary members relevant to the test
mock.Setup(_ => _.username).Returns(username);
var subject = new SomeClass(mock.Object);
//Act
//...invoke member to be tested
var actual = subject.SomeMethod();
//Assert
//...verify actual to expected behavior
Assert.AreEqual(actual, expected);
}
Reference Moq Quickstart to get a better understanding of how to use Moq
I would like to create a customization that configures AutoFixture to pass types it DOES have implementations for off to Moq instead. How can I do that generically?
To clarify, consider:
public class test
{
public string foo;
public test(IDictionary<string, string> stuffing)
{
foo = stuffing["bogus"];
}
}
[TestMethod]
public void testInjection()
{
var fixture = new Fixture();
bool didThrow;
try
{
var sut = fixture.Create<test>();
didThrow = false;
}
catch
{
didThrow = true;
}
Assert.IsTrue(didThrow);
}
The test passes. AutoFixture has provided me with a dummy collection compatible with IDictionary. I would like the test to fail... specifically, I'd like to hand the IDictionary off to Moq and get something that doesn't complain about missing keys by default.
I'd like to use something like fixture.UseAutoMoq().ForceRelay<Dictionary<string,string>>().
I'm also open to better suggestions... but consider the test class sealed. I'm testing into code that uses this pattern a lot and I want a test convention around it.
To do what you ask for, you can take the MockRelay added by AutoMoqCustomization and move it in front of the well-known-collections-builders:
[Fact]
public void PassByMovingAutoMoqRelay()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var relay = fixture.ResidueCollectors.OfType<MockRelay>().Single();
fixture.Customizations.Add(relay);
var sut = fixture.Create<MyClass>(); // Doesn't throw
}
However, I don't think it's a good idea, as most of the .NET collection interfaces are big fat LSP violations, and there's no guarantee that auto-mocking them will produce meaningful behaviours - I'd expect the opposite to be the case.
I'm new in unit testing.
Its suggested to use Factory method to create instance of class under test for maintainability reasons.
Like:
public class StringCalculatorTests
{
[Fact]
public void Add_EmptyString_ReturnZero()
{
var calculator = CreateCalculator();
int result = calculator.Add("");
result.Should().Be(0);
}
private static StringCalculator CreateCalculator()
{
//Some difficult object creation
var logger = Substitute.For<ILogger>();
var calculator = new StringCalculator(logger);
calculator.Initialize();
return calculator;
}
}
Everything nice: if API changes - i will change StringCalculator creation only in one place, not in every tests.
But what if i need to change a return value for some method of ILogger. Or I will use ILogger not as stub but as a mock:
[Fact]
public void Add_EmptyString_LogAboutEmptyInput()
{
var loggerMock = Substitute.For<ILogger>();
var calculator = new StringCalculator(loggerMock);
calculator.Initialize();
calculator.Add("");
logger.Received("Empty input.");
}
Now i can't use factory method, and if there are changes in API - i should go through my tests to change it.
I thought about property injection - but it may be not good local default for ILogger for example.
(i know - we usually have good default for logger, but it can be some another dependency)
I thought about optional parameters for factory method. But it seems to have logic. It's very simple but still logic.
Is there any good approach to solve this? Or it's good enough and it's a common situation to create instance just in class when we need it?
You can overload your factory method to accept a mock logger.
private static StringCalculator CreateCalculator(ILogger logger)
{
var calculator = new StringCalculator(logger);
calculator.Initialize();
return calculator;
}
Then you can create your mock logger in the test (possibly a separate factory method for the logger if the same mocking is used in multiple tests)
[Fact]
public void Add_EmptyString_LogAboutEmptyInput()
{
var loggerMock = //whatever code you need to set up your mock
var calculator = CreateCalculator(loggerMock);
calculator.Add("");
logger.Received("Empty input.");
}
I am writing a unit test and one of the issues that I encounter is null exception on a private class that is not part of DI or not being initialized on constructor parameters. Anyone can help me? Here's my code. My problem is that how to mock PPortalSessionVariables class.
Controller:
public class EducatorController : BaseController
{
//Note: PPortalSessionVariables class should NOT be part of IOC
private readonly IPPortalSessionVariables _ppsessionVariable = new PPortalSessionVariables();
private readonly IEducatorService _educatorService;
public EducatorController(IEducatorService educatorService)
{
_educatorService = educatorService;
}
public ActionResult Index()
{
//during test null exception occurs on _ppsessionVariable.CurrentChild.Id
var model = _educatorService.GetEducatorsForChild(Convert.ToInt64(_ppsessionVariable.CurrentChild.Id));
return View(model);
}
}
Test Class:
[TestClass]
public class EducatorControllerTests
{
public EducatorController CreateController(Mock<IEducatorService> educatorService = null)
{
educatorService = educatorService ?? new Mock<IEducatorService>();
HttpContext.Current = HttpMockHelpers.FakeHttpContextCurrent();
var controller = new EducatorController(educatorService.Object);
controller.SetFakeControllerContext("?site=2");
return controller;
}
[TestMethod]
public void Index_Get_ReturnIndexView()
{
var ppsessionVariable = new Mock<IPPortalSessionVariables>();
var controller = CreateController();
var child = new ChildModel();
child.Id = 0;
ppsessionVariable.Setup(x => x.CurrentChild).Returns(child);
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
}
}
There are two things that are really causing this headache for you:
The fact that _ppSessionVariable is private, and not exposed to the outside world
There is an assumption that IPPortalSessionVariables.CurrentChild should never return null, for all implementations of the interface
If you address either of these points, then your problem goes away.
Expose a public setter to allow the unit test to explicitly set the _ppsessionVariable to the mock object. Something like:
public void SetSessionVariable(IPPortalSessionVariables ppsessionVariable)
{
_ppsessionVariable = ppsessionVariable;
}
Refactor your code to prevent _ppsessionVariable.CurrentChild from returning null.
The simplest thing would probably be to initialize CurrentChild to a Null Object, in the PPortalSessionVariables constructor.
Your EducatorController is clearly very tightly coupled with PPortalSessionVariables. Till the time you have new PPortalSessionVariables() in the controller unit testing it in isolation will not be possible.
In order to fix this, make sure the EducatorController depends on an abstraction IPPortalSessionVariables instead of the concrete implementation.
Like others have already suggested, consider having a public setter for IPPortalSessionVariables or go ahead with a constructor injection.
Don't understand why you just don't use it as any other dependency injecting it via IoC. As far as Moq works you should mock that class but never will be able to set that object, maybe a workaround is create a setter for that property and call the property in your test passing the mock object.
EducatorController
public void SetPortalSession(IPPortalSessionVariables portal)
{
_ppsessionVariable = portal;
}
EducatorControllerTests
[TestMethod]
public void Index_Get_ReturnIndexView()
{
var ppsessionVariable = new Mock<IPPortalSessionVariables>();
var controller = CreateController();
controller.SetPortalSession(ppsessionVariable.object);
var child = new ChildModel();
child.Id = 0;
ppsessionVariable.Setup(x => x.CurrentChild).Returns(child);
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
}
Let's say I have a bunch of classes that look something like...
class Foo{
private Bar highlyCoupled = new highlyCoupled();
public bool DoTheThing(){
return highlyCoupled.doesTheThing();
}
}
Is it possible to use reflection to open up foo and inject (duck-punch may be a more correct term) some sort of mockHighlyCoupled in the place of highlyCoupled?
What about in this situation...
class DoubleFoo : Foo{
public bool DoTheOtherThing(){
return DoTheThing();
}
}
Can the inherited highlyCoupled have a mock inserted in it's place?
Refactoring the code so as to not require reflection isn't possible, unfortunately.
Since you can't refactor using a mocking framework could make this a bit easier for you. For Example:
TypeMock:
var fakeType = Isolate.Fake.Instance<SomeType>();
ObjectState.SetField(fakeType, "_somePrivateField", myValue);
Moq:
var fakeType = new Mock<SomeType>()
fakeType.Protected().Setup<SomeType>("_somePrivateField").Returns(myValue);
To be honest I haven't actually tried this out with Moq but I think it will do what you need.
You can indeed use reflection and a mocked type, but that type has to inherit from the original type (FieldInfo.SetValue will fail otherwise).
void Main()
{
var bar = new Bar();
var type = typeof(Bar);
// Get the type and fields of FieldInfoClass.
var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
fields[0].SetValue(bar, new FooMock()); // you can use new Foo() here too.
bar.Print();
}
class Foo {
public int i = 0;
}
class FooMock : Foo {
}
class Bar {
private Foo foo = new Foo();
public void Print() {
Console.WriteLine(i);
}
}
If you can't refactor at all (make highlyCoupled protected), then you're stuck using reflection. That will let you set the value of highlyCoupled without modification.
I generally agree with Rob; if you can't refactor this in order to make the dependency more loosely coupled (at least allow a derived class like a test proxy to override its default value), then reflection to set the value despite its visibility is pretty much the only way you can go.
The absolute least you could do is make the dependency protected. If this is possible now or at any point in the future, do it:
class Foo{
protected Bar highlyCoupled = new highlyCoupled();
public bool DoTheThing(){
return highlyCoupled.doesTheThing();
}
}
...
//in your test suite
class FooTestProxy:Foo
{
public FooTestProxy(Bar testMock)
{
highlyCoupled = testMock;
}
}
//now when testing, instantiate your test proxy and pass it the mocked object