I would like to inject a fake nHibernate session into my repository using FakeItEasy, then return a list of objects that are predefined within my test. Does anyone have experience doing this?
Here is the example test:
[TestFixture]
public class ProductionRepositoryTester
{
private ProductionRepository _productionRepository;
[SetUp]
public void SetupFixture()
{
const string propertyNumber = "123";
Tank tank = new Tank { PropertyNumber = propertyNumber };
var session = A.Fake<ISession>();
var sessionFactory = A.Fake<ISessionFactory>();
A.CallTo(session).WithReturnType<IList<Tank>>().Returns(new List<Tank> { tank });
_productionRepository = new ProductionRepository(session, sessionFactory);
}
[Test]
public void ProductionRepositoryCanGetTanks()
{
var tanks = _productionRepository.GetTanks();
Assert.AreNotEqual(0, tanks.Count(), "Tanks should have been returned.");
}
}
And here is the call within the actual ProductionRepository class:
public IEnumerable<Tank> GetTanks()
{
var tanks = Session.CreateCriteria(typeof(Tank)).List<Tank>();
return tanks;
}
Thanks in advance for any advice!
First of all I would advice against faking the NHibernate interfaces at all, this is (in my opinion) too low a level to unit test. It's probably better to have some integration tests for these scenarios. In other words, unit test all interaction with an abstraction for ProductionRepository (IProductionRepository) but stop there. Now, however, that's just my opinion and if you really want to do this I think you would have to change your fake-setup:
The session returns a criteria, not ever a IList directly. Therefore you'd have to have a fake criteria too:
var fakeCriteria = A.Fake<ICriteria>();
A.CallTo(fakeCriteria).WithReturnType<IList<Tank>>().Returns(new List<Tank> { tank });
A.CallTo(session).WithReturnType<ICriteria>().Returns(fakeCriteria);
(I hope I remember the criteria type correctly, I think it's ICriteria but I'm not a hundred percent sure.)
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.
My client wants to have 100% code coverage for all the projects. I have written few test cases very long back for Web API's using nUnit. But my client decided to use xUnit as a unit test framework using Moq as Mock framework.
As i have never worked on unit test case for sitecore project, could anyone please en-light us on the approach? As a start coudl anyone please write a sample test case for the below method? We are using GlassMapperFramework as a ORM.
public class RegistrationController : GlassController
{
public ActionResult RegistrationInitiation()
{
var someobject = GetDataSourceItem<IRegistrationMainContent>();
return View(someobject);
}
}
To test your Controllers, you will want to inject the Sitecore Context into the Controller. The GlassController has an overload method on it GlassController(ISitecoreContext). This is used to Unit Test your controllers. It also has other overloads if needed...
Here is more complete code you need to unit test the controller
private Mock<IRegistrationModel> RegistrationModel { get; set; };
private RegistrationController Controller { get; set; }
[TestInitialize]
public void Setup()
{
var mockSitecoreContext = new Mock<ISitecoreContext>();
this.RegistrationModel = new Mock<IRegistrationModel>();
this.RegistrationModel.SetupAllProperties();
mockSitecoreContext.Setup(sc =>sc.GetItem<IRegistrationModel
(It.IsAny<string>(), false, false)).
Returns(this.RegistrationModel.Object);
this.Controller = new RegistrationController {SitecoreContext =
mockSitecoreContext.Object }
}
[TestMethod]
public void Your_Unit_Test_Name()
{
//....perform unit test here
this.Controller.SitecoreContext = null;
var result = this.Controller.GetIndex() as ViewResult;
//Assert ....
}
Let me know if you have questions!
I need a jump start in testing the methods on my Business layer. Consider the Materials BLL object, how can I test the AddNewMaterial method for it?
interface IGenericRepository<TEntity>
{
TEntity Add(TEntity m);
}
public interface IMaterialRepository : IGenericRepository<Material>
{
}
public interface IUnitOfWork
{
IMaterialRepository Materials { get; private set;}
void Save();
}
public interface IUnitOfWorkFactory
{
IUnitOfWork GetUnitOfWOrk();
}
public class MaterialsBLL
{
private readonly IUnitOfWorkFactory _uowFactory;
//uowFactory comes from DI
public MaterialsBLL(IUnitOfWorkFactory uowFactory)
{
_uowFactory = uowFactory;
}
//TODO: test this
public Material AddNewMaterial(Material m)
{
using(var uow = _uowFactory.GetUnitOfWOrk())
{
var result = uow.Materials.Add(m);
uow.Save();
return result;
}
}
I am using Moq, and XUnit, but am very green. In general I want to do this:
Mock the repositories Add method.
Mock the UoW Materials property to return my repository mock.
Mock the UoWFactory to return the UoW mock.
Create the MaterialsBLL giving the mocked UoWFactory to the contstructor.
Verify that the AddNewMaterials calls the repository's Add, and the UoW's Save, etc.
It seems to me that, I maybe should be creating a Fake MaterialRepository, rather than mocking it? Any other advice? Here is a first crack:
[Fact]
public void TestGetMaterialById()
{
var materialList = GetMaterials();
var materialRepositoryMock = new Mock<IMaterialRepository>();
materialRepositoryMock.Setup(repo => repo.Get(4)).Returns(materialList.First());
var uowMock = new Mock<IUnitOfWork>();
uowMock.SetupProperty<IMaterialRepository>(uow => uow.Materials, materialRepositoryMock.Object);
var uowFactoryMock = new Mock<IUnitOfWorkFactory>();
uowFactoryMock.Setup(f => f.GetUnitOfWork()).Returns(uowMock.Object);
var materialsBll = new Materials(uowFactoryMock.Object);
var result = materialsBll.Get(4);
Assert.Equal(result.MaterialId, 4);
Assert.Equal(result.Name, "Four");
}
When you feel like you need several levels of nested mock objects, there's generally something wrong with your design.
The Law of Demeter warns us here that you should probably not tinker with uow.Materials in MaterialsBLL.
Besides, a Unit of Work is typically not the place to expose Repositories. The code that needs to access Materials will usually have a direct reference to an IMaterialsRepository, not ask it from the UoW, and then the Repository implementation might reference the UoW internally.
This leads to a flatter design and simplifies your production code as well as your tests.
I want to refactor a DLL to make it MEFable too. Should I unit test whether a class is decorated with [Export] or [Import] and other MEF attributes?
Your tests should focus more on the goal instead of the mechanism. Create tests that verify things like "if I throw types X, Y and Z together in a container, then I can pull an IFoo interface from the container", like this:
[Test]
public void Can_get_IFoo_from_container_with_Foo_Bar_Baz()
{
var catalog = new TypeCatalog(typeof(Foo), typeof(Bar), typeof(Baz));
using (var container = new CompositionContainer(catalog))
{
var test = container.GetExportedValue<IFoo>();
}
}
This is no longer a real "unit" test because it involves multiple classes and an IoC container. We just call them "composition tests".
After thinking some hours and reading some TDD blogs again I should say, YES, I have to test whether my class has MEF attributes or not.
So before refactoring my classes I write unit tests in that way:
[TestClass]
public class When_SampleClass_mefable
{
[TestMethod]
[TestCategory("LFF.Kabu.Win.Login.ViewModel.SampleClass")]
public void Should_SampleClass_be_marked_with_Export_Attibute()
{
//arrange
var info = (typeof (SampleClass));
//act
var attr = info.GetCustomAttributes(true);
var hasExportAttribute =
attr.Where(x => x.GetType() == typeof (ExportAttribute))
.Where(x => ((ExportAttribute)x).ContractType == typeof(SampleClass))
.Count() > 0;
//assert
Assert.IsTrue(hasExportAttribute, "SampleClass is not marked with Export.");
}
}
For other MEF attributes like [ImportingConstructor] or [PartCreationPolicy] I do it the same way.
a very simple method, but don't know what's to test!
I'd like to test this method in Business Logic Layer, and the _dataAccess apparently is from data layer.
public DataSet GetLinksByAnalysisId(int analysisId)
{
DataSet result = new DataSet();
result = _dataAccess.SelectAnalysisLinksOverviewByAnalysisId(analysisId);
return result;
}
All Im testing really is to test _dataAccess.SelectAnalysisLinksOverviewByAnalysisId() is get called!
here's my test code (using Rhino mock)
[TestMethod]
public void Test()
{
var _dataAccess = MockRepository.GenerateMock<IDataAccess>();
_dataAccess.Expect(x => x.SelectAnalysisLinksOverviewByAnalysisId(0));
var analysisBusinessLogic = new AnalysisLinksBusinessLogic(_dataAccess);
analysisBusinessLogic.GetLinksByAnalysisId(0);
_dataAccess.VerifyAllExpectations();
}
Let me know if you writing the test for this method what would you test against?
Many Thanks!
Your proposed example test doesn't test the method in question, but rather an overload with the same name.
Another issue is that the expectation set up for the mock doesn't match the method called. Again, it's another overload.
The third thing that comes into my mind is that you don't need to perform an interaction-based test here. Since the method under test has a return value, you can perform a simple state-based test.
Here's one possible alternative:
[TestMethod]
public void Test()
{
var id = 1;
var expectedResult = new DataSet();
var dataAccess = MockRepository.GenerateStub<IDataAccess>();
dataAccess.Stub(x => x.SelectAnalysisLinksOverviewByAnalysisId(1))
.Return(expectedResult);
var analysisBusinessLogic = new AnalysisLinksBusinessLogic(dataAccess);
var result = analysisBusinessLogic.GetLinksByAnalysisId(id);
Assert.AreEqual(expectedResult, result);
}
actually what you think this little tweak?
dataAccess.Expect(x =>
x.SelectAnalysisLinksOverviewByAnalysisId(1)).Return(expectedResult);
Assert.AreEqual(expectedResult, result);
dataAccess.VerifyAllExpectations();
that way we doing the Assert as well as expect the SelectAnalysisLinksOverviewByAnalysisId() being called
What's your thoughts?