Having some issues wrapping my head around class instantiation and TestDriven.Net(v4.0.3478) or XUnit(v2.2.0), RhinoMocks(v3.6.1), and structuremap.automocking(v4.0.0.315).
Given this code:
public class Tests1
{
[Fact]
public void passing_test()
{
var mocker = new RhinoAutoMocker<Subject>();
mocker.Get<IData>().Stub(x => x.Strings).Return(new List<string> {""});
var result = mocker.ClassUnderTest.GetStrings();
result.Count().ShouldEqual(1);
}
}
public class Tests2
{
[Fact]
public void passing_test()
{
var mocker = new RhinoAutoMocker<Subject>();
mocker.Get<IData>().Stub(x => x.Strings).Return(new List<string> {""});
var result = mocker.ClassUnderTest.GetStrings();
result.Count().ShouldEqual(1);
}
}
public class Subject
{
private readonly IData _data;
public Subject(IData data)
{
_data = data;
}
public IEnumerable<string> GetStrings()
{
return _data.Strings;
}
}
public interface IData
{
IEnumerable<string> Strings { get; set; }
}
All tests run fine when I right click -> Run Test(s) on specific test method or a specific class definition.
Tests fail when I right click on project, folder containing tests or the namespace definition of the class above.
The errors are NullReferenceException, when doing asserts, it seems to be the stub's data. It's random, sometimes Tests1.passing_test fails, sometimes Tests2.passing_test fails. Never both.
Thinking it has to with RhinoAutoMocker and/or the MockRepository not being reset between test fixtures?
UPDATE: simplified the code to show the problem, also given code is complete, using NUnit [Test] instead of XUnit [Fact] attributes works, everything behaves as normal.
In your example, you have two separate test classes.
By default, xUnit v2 will run these tests in parallel.
I have experienced the same issue, but in my case using the static MockRepository.GenerateMock.
The static class being used across the parallel tests results in exceptions.
The seeming randomness of the test failures depends on which tests run first.
There are two alternatives I can see.
1. Tests in a single class - not really workable
2. Use the XUnit Collection attribute to place all tests classes in the same collection - this worked for me.
see: http://xunit.github.io/docs/running-tests-in-parallel.html
Another alternative is to turn off parallelism for xUnit using the following attribute in your test assembly
[assembly: CollectionBehavior(DisableTestParallelization = true)]
Related
I been trying to figure out how i can unit test service and so far have got nowhere.
I am using xUnit and NSubstitute (as advised by friends), below is the simple test that i want to run (which fails currently).
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
My rally service class makes a simple call to the db to get all Rally entites and returns those:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
Any guidance would be appreciated.
Since you use .NET Core, I assume you also use Entity Framework Core. While it was possible to mock most of the operations in the previous EF version, however the EF Core suggests to use in-memory database for unit testing. I.e. you don't need to mock RallyDbContext, hence NSubstitute is not needed for this particular test. You would need NSubstitute to mock the service when testing a controller or application using the service.
Below is your Test1 written using in-memory database.
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
A working test application with this unit test is in my GitHub for your reference. I used SQL Express in the actual app.
I don't think it is standard to have a unit test constructor with a parameter. The unit test runner will new up this class, and unless you are using something that will auto-inject that parameter I think the test will fail to run.
Here is a standard fixture layout:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
If you need a common setup between tests, you can use a parameterless constructor and do common initialisation there.
In terms of the specific class you are trying to test, you need to make sure your RallyDbContext is in a known state to repeatably and reliably test. You may want to look up answers specific to testing Entity Framework for more information.
I have a class that I want to write unit tests for. I'm using StructureMap (2.6.3) in the project and I have some problems with that.
For testing I use Nunit (2.6.0.12054) and RhinoMocks (3.6).
Normally i inject my dependencies in the constructor of my classes and then it's easy to substitute the dependencies with mocks in my unit tests. But there are a few cases where I can't do that, where I have no control over when the class under test is created. In these cases I use ObjectFactory.GetInstance() to get the dependencies.
public class MyClass
{
public int MyMethod(string parameter)
{
var myDependency = ObjectFactory.GetInstance<IMyDependency>();
try
{
return myDependency.CalculateValue(parameter);
}
catch (Exception ex)
{
//Suppress exception.
return 0;
}
}
}
For this class and method I want to write two tests. First I want to to test that the dependency is called and the value it calculates is returned by the class under test. Second, the dependency might throw an exception and I want to test that this exception is suppressed by the class under test and that it return zero in that case.
[TestFixture]
public class MyClassTests()
{
[Test]
public void MyMethod_DependencyReturnsValue_ReturnsValueFromDependency
{
//Arrange.
const int valueFromDependencyStub = 333;
var myDependencyStub = MockRepository.GenerateStub<IMyDependency>();
myDependencyStub.Stub(x => x.CalculateValue()).Return(valueFromDependencyStub);
ObjectFactory.Inject<IMyDependency>(myDependencyStub);
var target = new MyClass();
//Act.
var result = target.MyMethod("test");
//Assert.
Assert.AreEqual(valueFromDependencyStub, result);
}
[Test]
public void MyMethod_DependencyThrowsException_ReturnsZero
{
//Arrange.
var myDependencyStub = MockRepository.GenerateStub<IMyDependency>();
myDependencyStub.Stub(x => x.CalculateValue()).Throw(new Exception());
ObjectFactory.Inject<IMyDependency>(myDependencyStub);
var target = new MyClass();
//Act.
var result = target.MyMethod("test");
//Assert.
Assert.AreEqual(0, result);
}
}
Both these tests work if I run them individually, but if I run the both it does not work. I my real case the second test, where the stubbed dependency throws an exception, runs first. When the other test runs the stubbed dependency still throws an exception.
The problem, as I understand it, is that I'm using the global ObjectFactory and inject my stub into that. That would probably work if I could clear the ObjectFactory after each test, but I found no way to do that. ObjectFactory.EjectAllInstancesOf() sounded like something that would work, but it doesn't.
How do I solve this? Either by changing my test or by actually rewriting the class under test.
I've got the following code and I need help to write a unit test for it. I'm using Moq library.
Here's the deal. I have a business class with a dependency to a repository (interface), so I can use it to save my entities to the database. My entity is basically a list of strings. The method AddAndSave, from MyBusinessClass, grab the value it receives as a parameters, put it into the list and call Save method from IRepository. Then, I clear the list of my entity. The code below show this example (I've made it simple so I can explain it here).
There's a unit test, too.
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace TestesGerais
{
public class MyEntity
{
public MyEntity()
{
MyList = new List<string>();
}
public List<string> MyList { get; set; }
}
public interface IRepository
{
void Save(MyEntity entity);
}
public class MyBusinessClass
{
public IRepository Repository { get; set; }
private MyEntity _entity = new MyEntity();
public void AddAndSave(string info)
{
_entity.MyList.Add(info);
Repository.Save(_entity);
_entity.MyList.Clear(); // for some reason I need to clear it
}
}
[TestClass]
public class UnitTest10
{
[TestMethod]
public void TestMethod1()
{
var mock = new Mock<IRepository>();
MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
b.AddAndSave("xpto");
mock.Verify(m => m.Save(It.Is<MyEntity>(x => x.MyList[0] == "xpto")), Times.Exactly(1));
}
}
}
My unit-test check if the IRepository's Save method was called with its parameter (an entity) having one element in the list, and having the value "xpto" in this element.
When I run this test, it turns red with the error message "Test method TestesGerais.UnitTest10.TestMethod1 threw exception:
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index".
Ok, this is caused by the list that has been cleaned. If I comment the line "_entity.MyList.Clear();", everything goes well.
My question is: how can I test this without commenting the "Clear" line in my business class, and making sure that my repository's method is called passing the specific value (entity with one element with value "xpto")?
Thanks
I've changed my unit test using the Callback feature of Moq. This way, I can setup the mock so when AddAndSave is called, the parameter it receives is saved into a variable from my unit test, and I can assert it later.
[TestMethod]
public void TestMethod1()
{
var mock = new Mock<IRepository>();
string result = string.Empty;
mock.Setup(m => m.Save(It.IsAny<MyEntity>())).Callback((MyEntity e) => { result = e.MyList[0]; });
MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
b.AddAndSave("xpto");
Assert.AreEqual(result, "xpto");
}
You could split your method up a bit. "AddAndSave" isn't all it does. You could then just test the behaviour of the adding and saving bit in isolation.
I have approximately 5-6 reports, they are structured the same, using Watin, I'm testing each one of these reports.
I have a shared test, I call "ReportBaseTests"..
public class ReportBaseTests
{
public string MenuName { get; set; }
public ReportBaseTests(string name)
{ this.MenuName = name; }
[TestMethod]
public void Perform_Invalid_Date_Range()
{
}
}
but in each of my tests, I have...
[TestClass]
public class Report1Tests : ReportBaseTests
{
public Report1Tests()
: base("Report 1")
{ }
}
This works... each report will have a seperate Perform_Invalid_date_range, and it'll goto a different page... I was hoping someone had a better way to do this, as it also produces a seperate "non-runnable" test for the shared test since I didn't include the [TestClass]
Now, I know I could use NUnit and pass in arguments, however, I'm sticking with MSTest for the time being
If you wanted, you could add TestContext support to your tests and have the ReportBaseTests.Perform_Invalid_Date_Range() parse the TestContext.FullyQualifiedTestClassName. For a simple test I think that's over kill.
For your solution: just put the [TestClass] attribute on ReportBaseTests and then mark ReportBaseTests as abstract. The "non-runnable" tests will disappear.
I have two test fixtures that have a common parent. Although the tests involve SQLite/NHib type of stuff, which are usually a bit of a at first, there is something I don't understand about NUnit that I'm hoping will help be fix these tests.
The good news is that if I run (via TestDriven.Net) both the subclassed TestFixtures without selecting the common parent, all tests succeed. But if I include the common parent in the run, I get failures (presumably because my NHib session has been disposed or lost it's binding).
Can anyone explain why the two tests succeed on their own but not with
the parent, and if there is someway to enforce the successful
behavior?
Cheers,
Berryl
public class ActivityTestFixture : GreenQueryOnlySQLiteTestFixture
{
protected IProjectDao _projectDao;
protected IDao<Account> _accountDao;
protected override void OnFixtureSetUp()
{
base.OnFixtureSetUp();
_projectDao = DataFactory.GetProjectDao(_sessionFactoryContext.SessionFactory);
_accountDao = DataFactory.GetAccountDao(_sessionFactoryContext.SessionFactory);
}
}
[TestFixture]
public class AccountDaoTests : ActivityTestFixture
{
[Test]
public void FindAll_IsEquivalentToSeeds() {
IList<Account> found;
using (var tx = _session.BeginTransaction()) {
found = _accountDao.FindAll();
tx.Commit();
}
found.AssertUnsavedValueSequenceEqual(ActivitySubjectSeeds.AllAccounts.ToAr ray());
}
}
[TestFixture]
public class ProjectDaoTests : ActivityTestFixture
{
[Test]
public void FindAll_IsEquivalentToSeeds()
{
IList<Project> found;
using (var tx = _session.BeginTransaction())
{
found = _projectDao.FindAll();
tx.Commit();
}
found.AssertUnsavedValueSequenceEqual(ActivitySubjectSeeds.Projects.ToArray ());
}
}
Not sure what the error that you're getting is, but it's likely because you have some kind of static fields in the GreenQueryOnlySQLiteTestFixture class. The way NUnit works is that a fixture lives for the lifetime of the tests inside of it. So it is only created once for all of the tests. This is different from xUnit which lives for the lifetime of one test.
Without seeing the entire implementation it's hard to see what is wrong. However, you can remove the TestFixtureAttribute from your parent fixture since it does not appear to have any tests anyway.