NUnit use different objects as Test Cases - c#

I am trying to write an Update Test for different products (which are classes in this case) and different time steps :
public class UpdateTest
{
private static Product ProductLastYear;
private static Product ProductTwoYearsAgo;
public UpdateTest(Product product)
{
var previousReleasedProducts = new Products();
ProductLastYear = previousReleasedProducts.GetProduct(Years.GetLastYear());
ProductTwoYearsAgo = previousReleasedProducts.GetProduct(Years.GetTwoYearsAgo());
}
Each product needs to be installed, and afterwards it is checked if the installation was successful (this is basically a pre-step before the Update). Right now, I am using two Tests for this:
[Test, Category("UpdateLastYear")), Order((int) NunitTestOrderEnum.Order.First)]
public void InstallPreviousReleasedProduct()
{
using (var controller = new BootstrapperController(ProductLastYear))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(ProductLastYear);
Assert.That(successfulInstallation, Is.True);
}
[Test, Category("UpdateTwoYearsAgo"), Order((int) NunitTestOrderEnum.Order.First)]
public void InstallTwoYearsAgoProduct()
{
using (var controller = new BootstrapperController(ProductTwoYearsAgo))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(ProductTwoYearsAgo);
Assert.That(successfulInstallation, Is.True);
}
Now, both tests have some code redundancy, which I would like to avoid. I was thinking about using TestCases for this, something like :
[TestCase(ProductLastYear), Category("UpdateLastYear"), Order((int) NunitTestOrderEnum.Order.First)]
[TestCase(ProductTwoYearsAgo), Category("UpdateTwoYearsAgo"), Order((int) NunitTestOrderEnum.Order.First)]
public void InstallPreProduct(Product product)
{
using (var controller = new BootstrapperController(product))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(product);
Assert.That(successfulInstallation, Is.True);
}
Is something like this possible? I tried different Syntax for that approach, but it does not seem to work that easily.

You can only use compile-time constants within attributes. However your static fields are no constants.
You can use the TestCaseSource-attribute:
[TestCaseSource(nameof(ProvideTestcases))]
public void InstallPreProduct(Product product)
{
using (var controller = new BootstrapperController(product))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(product);
Assert.That(successfulInstallation, Is.True);
}
public static IEnumerable<TestCaseData> ProvideTestcases()
{
yield return new TestCaseData(ProductLastYear).SetCategory("UpdateLastYear");
yield return new TestCaseData(ProductTwoYearsAgo).SetCategory("UpdateTwoYearsAgo");
}
However that assumes your static fields are already initialized, which isn't the case. So you need a static constructor for your testclass.
[TestFixture]
public UpdateTest
{
public static ProductLastYear;
public static ProductTwoYearsAgo;
static
{
ProductLastYear = ...;
ProductTwoYearsAgo = ...;
}
}
This is pretty much boilerplate for so little duplication. So it's a tradeoff if or of it not this is worth the afford.
Another opportunity is to introduce some static constant, like an enum that reflects the property to be used:
[TestCase(MyEnum.LastYear), Category("UpdateLastYear")]
[TestCase(MyEnum.TwoYearsAgo), Category("UpdateTwoYearsAgo")]
public void InstallPreProduct(MyEnum product)
{
var Product = product == MyEnum.LastYear ?
ProductLastYear :
ProductTwoYearsAgo ;
using (var controller = new BootstrapperController(product))
{
controller.Install();
}
var successfulInstallation = InstallationValidator.ValidateInstall(product);
Assert.That(successfulInstallation, Is.True);
}
An enum is a constant expression, so you can easily use it within the test-attributes.

Related

Unit Test Static methods in a class using MS Fakes C#

Here is the class I am trying to mock. Helper class that has a static method. Which takes in a dataTable.
public class DataTableHelpers
{
public static ArrayList GetDataTableColumns(DataTable dataTable)
{
if (dataTable == null)
{
throw new ArgumentNullException(nameof(dataTable));
}
var columnsCount = dataTable.Columns.Count;
var columnHeadings = new ArrayList();
for (var i = 0; i < columnsCount; i++)
{
var dataColumn = dataTable.Columns[i];
columnHeadings.Add(dataColumn.ColumnName.ToString());
}
return columnHeadings;
}
}
Tried using ShimsContext. Here is the snippet I have come up with. Want to mock when datatable is null and not null.
public void GivenDatatableIsNUllShouldThrowNullException()
{
var expected = new ArrayList();
//ARRANGE
using (ShimsContext.Create())
{
dataTableHelpers = new DataTableHelpers();
//ACT
var result = ShimDataTableHelpers.GetDataTableColumnsDataTable = (s) =>
{
Should.Throw<ArgumentNullException>(() =>
{
});
throw new ArgumentNullException(nameof(s));
};
//Assert
Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AreNotEqual(result, expected);
}
}
Your question is a little unclear but I think what you're after is a way to test code that is using the given static helper method. It's easy to test the static helper, it's not so easy to test code that's using those helpers. When you run into something like I've found it best to refactor that code to not use static helpers. Instead push that code into a class that you can abstract and inject into places you need it. But sometimes that's easier said than done.
As a stop gap you can incrementally move to that direction by introducing a class to hold the actual code that you can then swap out when testing. This doesn't use MS Fakes but it's a technique that you can use to help make your code more testable.
I'm sorry I can't recall who first came up with this method, it certainly wasn't me. But here's the idea:
Create a class to hold the logic:
public class DataTableHelperImpl : IDataTableHelperImpl
{
public ArrayList GetDataTableColumns(DataTable dataTable)
{
if (dataTable == null)
{
throw new ArgumentNullException(nameof(dataTable));
}
var columnsCount = dataTable.Columns.Count;
var columnHeadings = new ArrayList();
for (var i = 0; i < columnsCount; i++)
{
var dataColumn = dataTable.Columns[i];
columnHeadings.Add(dataColumn.ColumnName.ToString());
}
return columnHeadings;
}
}
With the associated interface that you can then mock:
public interface IDataTableHelperImpl
{
public ArrayList GetDataTableColumns(DataTable dataTable);
}
Then use this in your static helper:
public static class Helper
{
public static IDataTableHelperImpl implementation = new DataTableHelperImpl();
public static ArrayList GetDataTableColumns(DataTable dataTable)
{
return implementation.GetDataTableColumns(dataTable);
}
}
Now in your test you can swap out that class to mock whatever behavior you want.
[Fact]
public void Test1()
{
var implMock = Mock.Of<IDataTableHelperImpl>();
Helper.implementation = implMock;
// whatever you need to test...
}

FakeItEasy and matching Anonymous types

I having trouble matching an expectation that uses anonymous types. I am new to FakeItEasy but not to mocking and would like some guidance on what is the proper way to match arguments. I understand from this thread (https://github.com/FakeItEasy/FakeItEasy/issues/532#issuecomment-135968467) that the "predicate can be extracted to a method". I have created a method that matches a Func<object, bool> signature named IsMatch to hide the reflection (similar to the link#comment included above) and the FakeItEasy argument parser still doesn't pick it up. Here is a failing test. How can I check the anonymous type?
using System;
using System.Collections.Generic;
using FakeItEasy;
using Xunit;
namespace UnitTests
{
public class Tests
{
private Dictionary<string, object> _properties;
[Fact]
public void AnonymousTest()
{
string id = "123456ABCD";
string status = "New Status";
var fake = A.Fake<IRepository>();
var logic = new BusinessLogic(fake);
_properties = new Dictionary<string, object>()
{
{"Status__c", status},
{"UpdatedOn__c", DateTime.Today},
{"IsDirty__c", 1},
};
var expectation = A.CallTo(() => fake.UpdateDatabase(id, A<object>.That.Matches(anon => IsMatch(anon))));
logic.ChangeStatus(id, status);
expectation.MustHaveHappenedOnceExactly();
}
private bool IsMatch(object o)
{
foreach (var prop in _properties)
{
if (!o.GetType().GetProperty(prop.Key).GetValue(o).Equals(prop.Value))
return false;
}
return true;
}
}
public interface IRepository
{
void UpdateDatabase(string id, object fields);
}
public class BusinessLogic
{
private IRepository _repo;
public BusinessLogic(IRepository repo)
{
_repo = repo;
}
public void ChangeStatus(string id, string status)
{
var fields = new
{
Status__c = status,
UpdatedOn__c = DateTime.Today,
IsDirty__c = true
};
_repo.UpdateDatabase(id, fields);
}
}
}
#philipwolfe, the structure of your test looked right to me, so I tried it out.
It passes when I change
{"IsDirty__c", 1}
to
{"IsDirty__c", true}
to match the object built in ChangeStatus method.

Moq Verify with anonymous type parameter

I have the following test, with supporting classes, but I can't figure out how to verify the call on the dependency.
[TestFixture]
public class AnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var towns = new List<Town>
{
new Town { Name = "Lifford", County = "Donegal", Country="Ireland", Population = 1658 },
new Town { Name = "Ballyshannon", County = "Donegal", Country="Ireland", Population = 2504 },
new Town { Name = "Buxton", County = "Derbyshire", Country="United Kingdom", Population = 13599 },
};
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething(towns);
// Assert
// The following line needs to be fixed.
dependency.Verify(d => d.Execute(It.IsAny<IEnumerable<object>>(), It.IsAny<Func<object, decimal?>>()));
}
}
public interface IDependency
{
void Execute<T>(IEnumerable<T> collection, Func<T, decimal?> rateSelector);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(IEnumerable<Town> towns)
{
var counties = towns.GroupBy(t => new {t.Country,t.County});
foreach (var county in counties)
{
dependency.Execute(county, c => c.Population);
}
}
}
public class Town
{
public string Name { get; set; }
public string County { get; set; }
public int Population { get; set; }
public string Country { get; set; }
}
According to Moq's test output, the performed invocations are:
Dependency.Execute(System.Linq.Lookup`2+Grouping[<>f__AnonymousType0`2[System.String,System.String],UniFocus.Staffscope4.Tests.Town], System.Func`2[UniFocus.Staffscope4.Tests.Town,System.Nullable`1[System.Decimal]])
I see plenty of questions regarding anonymous parameters in Moq (such as this and this and this), but can't find anything relating to using an anonymous type as the actual type parameter.
What can be put in the Verify line so that it actually verifies the call inside?
Note: My example IDependency doesn't return a value (it's already complex enough, I think), but there will be bonus kudos for answers that implictly or explicitly address Setup() as well as Verify().
Update
Jesse's solution only passes the test because I made a bad choice when crafting my example. I should have realised that any IGrouping<out TKey, out TElement> is also an IEnumerable<TElement>. Is there a more universal solution?
Update 2
I feel like my original example was possibly too elaborate and didn't represent well the actual title of my question. Is there any solution that works for this more straightforward and to-the-point example?
using Moq;
using NUnit.Framework;
namespace Tests
{
[TestFixture]
public class SimpleAnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething("Donegal", "Lifford");
// Assert
// This verify works for both calls to Execute()
dependency.Verify(d => d.Execute(It.IsAny<object>()), Times.Exactly(2));
// This verify should specifically refer to only the first call to Execute()
dependency.Verify(d => d.Execute(It.IsAny</*HowToRepresentAnonymousTypeHere*/object>()), Times.Once);
}
public interface IDependency
{
void Execute<T>(T thing);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(string county, string town)
{
dependency.Execute(new { county, town });
object someUnknownObject = "";
dependency.Execute(someUnknownObject);
}
}
}
}
The accepted answer doesn't work for me, I believe it's because the tests and the object in question are in a different assembly so Moq doesn't know how to reconcile the types and does not match them.
Instead, I created the following helper methods that can verify that the anonymous type provided has the correct fields and values:
public static class AnonHelpers
{
public static object MatchAnonymousType(object expected)
{
return Match.Create(Matcher(expected));
}
private static Predicate<object> Matcher(object expected)
{
return actual =>
{
var expectedProp = expected.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(expected));
var actualProp = actual.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(actual));
foreach (var prop in expectedProp)
{
if (!actualProp.ContainsKey(prop.Key))
return false;
if (!prop.Value.Equals(actualProp[prop.Key]))
return false;
}
return true;
};
}
}
They can be used like so:
var anon = new { SomeKey = "some value", SomeOtherKey = 123 };
myMock.Setup(x => x.MyMethod(personIDs, AnonHelpers.MatchAnonymousType(anon))).Verifiable();
This will create a matcher that will use reflection to match the anonymous type based on it's keys and values and then you can use normal verification to see when it's been called.
Since the types are known in the context of the test, you could provide the specific type arguments to the Verify call. The following change got the test to pass:
dependency.Verify(d =>
d.Execute(It.IsAny<IEnumerable<Town>>(), It.IsAny<Func<Town, decimal?>>()));
The same should also work for setups.
With regards to the example in Update 2, the following passes, but it requires knowledge of the inner workings of the DoSomething() method and as far as I know it's the only way to make it work:
var anonymousType = new {county = "Donegal", town = "Lifford"};
dependency.Verify(d => d.Execute(anonymousType), Times.Once);

Passing multiple delegate parameters to extension function as a list

Consider the class hierarchy below
public class animal
{
}
public class lion:animal
{
}
public class cat:animal
{
}
public class Forest
{
public List<lion> lionlist = new List<lion>();
public List<cat> catlist = new List<cat>();
}
I need all the animals from a forest.
Extension function to retrieve all the animals from a forest
public static IEnumerable<TInnerObject> GetInnerBaseObjects<TInnerObject, TWrapperObject>(this TWrapperObject source,List< Func<TWrapperObject, IEnumerable<TInnerObject>>> innerObjectlist)
{
List<TInnerObject> retlist = new List<TInnerObject>();
innerObjectlist.ForEach(x =>
{
if (x(source) != null)
{
retlist.AddRange(x(source));
}
});
return retlist;
}
All is well. But at the point of usage the extension function usage is a bit messy
void somefunction(Forest obj)
{
//.....
var res = obj.GetInnerBaseObjects(new List<Func<Forest, IEnumerable<animal>>>()
{
(x)=>x.catlist , (y)=>y.lionlist
});
}
The instantiation of the delegate list at the point of use is a bit messy. I would prefer it simpler like below code. Of course it is not valid code!
var res = obj.GetInnerBaseObjects(
{
(x)=>x.catlist , (y)=>y.lionlist
});
Any ideas to simplify this at the point of use.I don't mind rewriting the extension function
Personally, I would probably create a third property or method on Forest to do this. However, assuming you have good reasons, have you considered using params?
public static IEnumerable<TInnerObject> GetInnerBaseObjects<TInnerObject, TWrapperObject>(this TWrapperObject source, params Func<TWrapperObject, IEnumerable<TInnerObject>>[] innerObjectlist)
{
return innerObjectlist.SelectMany(f => f(source));
}
Usage:
forest.GetInnerBaseObjects<animal, Forest>(f => f.catlist, f => f.lionlist);

How can I get StructureMap's AutoMocker to mock fake data?

I'm currently trying to implement StructureMap's AutoMocking functionality and I need help with getting the mocked .
I have a Test method as follows:
[Test]
public void DirctoryResult_Returns_Groups()
{
var autoMocker = new RhinoAutoMocker<GroupController>(MockMode.AAA);
GroupController controller = autoMocker.ClassUnderTest;
var directoryResult = controller.DirectoryResult("b");
var fundDirectoryViewModel = (FundDirectoryViewModel)directoryResult.ViewData.Model;
Assert.IsNotNull(fundDirectoryViewModel.Groups);
}
Currently the test is failing because fundDirectoryViewModel.Groups is null.
The real implementation of DirectoryResult is as follows:
private readonly IGroupService _groupService;
public PartialViewResult DirectoryResult(string query)
{
return PartialView(new FundDirectoryViewModel
{
Groups =_groupService.GetGroupsByQuery(query)
});
}
where _groupService.GetGroupsByQuery(query) uses an interface to IGroupRepository to read data from the database. Of course, I don't want my test to read data from the actual database, but can somebody tell me how to get mock data for it?
What do I need to do to get the AutoMocker to mock the fake data for me?
update:
for reference, this is the definition of GroupService & GroupRepository
public class GroupService : IGroupService
{
private readonly IGroupRepository _groupRepository;
public GroupService(IGroupRepository groupRepository)
{
_groupRepository = groupRepository;
}
public IList<CompanyGroupInfo> GetGroupsByQuery(string query)
{
return _groupRepository.GetGroupsByQuery(query);
}
}
public class GroupRepository : DataUniverseRepository, IGroupRepository
{
public GroupRepository(ISession session)
{
_session = session;
}
public IList<CompanyGroupInfo> GetGroupsByQuery(string query)
{
// dig into the database and return stuff with _session..
}
}
I've been informed that the question was wrong. Automocker doesn't mock data like that. It's up to me to specify the fake data with Rhino Mocks.
This works:
[Test]
public void DirctoryResult_Returns_Groups()
{
var service = autoMocker.Get<IGroupService>();
service.Expect(srv => srv.GetGroupsByQuery(Arg<string>.Is.Anything))
.Return(new List<CompanyGroupInfo>
{
new CompanyGroupInfo(),
new CompanyGroupInfo(),
new CompanyGroupInfo()
});
service.Replay();
var directoryResult = _controller.DirectoryResult("b");
var fundDirectoryViewModel = (FundDirectoryViewModel)directoryResult.ViewData.Model;
Assert.That(fundDirectoryViewModel.Groups.Count, Is.EqualTo(3));
service.AssertWasCalled(srv => srv.GetGroupsByQuery(Arg<string>.Is.Equal("b")));
}

Categories