I have service CarTankService as shown below. It has Add method which i want to test. To be more detailed i would like to check whether AddTank (inside Add) will be reached.
public class CarTankService : ICarTankService
{
private readonly ITankQuery _tankQuery;
private readonly CarClient _carClient;
public CarTankService(ITankQuery tankQuery)
{
_tankQuery = tankQuery;
_carClient = new CarClient();
}
public ObservableCollection<CarTank> GetTanks() => _carClient.Tanks;
public void GenerateNewList() => _carClient.GenerateNewTanksList();
public virtual void Add(CarTank tank)
{
if (_tankQuery.isExist(tank.Number)) throw new OwnException()
_carClient.AddTank(tank);
}
public virtual void Remove(CarTank tank) => _carClient.RemoveCarTank(tank);
}
This is my test method class:
[TestFixture]
class CarTankServiceTests
{
private Mock<ITankQuery> TankQuery { get; set; }
private ICarTankService CarTankService { get; set; }
private Mock<CarClient> CarClient { get; set; }
[SetUp]
public void SetUp()
{
TankQuery = new Mock<ITankQuery>();
CarClient = new Mock<CarClient>();
CarTankService = new CarTankService(TankQuery.Object);
}
[Test]
public void Add_NotExistReferenceNumber_AddTankReached()
{
TankQuery.Setup(uow => uow.isExist(It.IsAny<int>())).Returns(false);
CarTankService.Add(new CarTank());
CarClient.Verify(uow => uow.AddTank(It.IsAny<ClientTank>()),Times.Once);
}
}
CarClient.Verify for AddTank always show it was 0 occurence in test, which in this case is not true. I am not sure but I think it's because CarClient model class because it's not injected directly insdie my service it always shows 0. AM i right? Is there any option to test it?
If you mock your CarClient you have to setup all methods you want to use in your test (here AddTank). In you code we have two CarClient instances, one is mocked in your test and another is initialized in your constructor of CarTankService. So, you are calling the latter case while verifying the mocked one.
If you convert the CarClient to an interface and inject it, The solution is something like this:
[TestFixture]
class CarTankServiceTests
{
private Mock<ITankQuery> TankQuery { get; set; }
private ICarTankService CarTankService { get; set; }
private Mock<CarClient> CarClient { get; set; }
[SetUp]
public void SetUp()
{
TankQuery = new Mock<ITankQuery>();
CarClient = new Mock<CarClient>();
CarTankService = new CarTankService(TankQuery.Object);
}
[Test]
public void Add_NotExistReferenceNumber_AddTankReached()
{
TankQuery.Setup(uow => uow.isExist(It.IsAny<int>())).Returns(false);
CarTankService.Add(new CarTank());
CarClient.Setup(a=>a.AddTank(/*write you loginc*/));
CarClient.Verify(uow => uow.AddTank(It.IsAny<ClientTank>()),Times.Once);
}
}
Here is more explanation:
When you write CarTankService = new CarTankService(TankQuery.Object); in your test, it creates a new instance on your class (_carClient = new CarClient();), so the class has it's own instance, while the test class has it own too (CarClient = new Mock<CarClient>();) which is mocked. This line of code CarTankService.Add(new CarTank()); adds the tank to the instance of class, while in your test, you are verifying the instance of test class which has no tank (CarClient.Verify(uow => uow.AddTank(It.IsAny<ClientTank>()),Times.Once);).
Related
I have these two tests (stripped to the bare bones to replicate the error):
[TestFixture]
public class CreditorMapperTests
{
private IAbcContext _AbcContext;
[SetUp]
public void Setup()
{
_AbcContext = Substitute.For<IAbcContext>();
_AbcContext.CompanyInfo.Returns(x => new CompanyInfo(Arg.Any<Guid>()));
}
[Test]
public void A()
{
Creditor publishDocument = new Creditor();
publishDocument.CompanyExternalId = _AbcContext.CompanyInfo.UniqueId;
}
[Test]
public void B()
{
Creditor publishDocument = new Creditor();
publishDocument.CompanyExternalId = _AbcContext.CompanyInfo.UniqueId;
}
}
public interface IAbcContext
{
CompanyInfo CompanyInfo { get; }
}
public class CompanyInfo
{
public CompanyInfo(Guid uniqueId)
{
UniqueId = uniqueId;
}
public readonly Guid UniqueId;
}
public class Creditor
{
public Guid CompanyExternalId { get; set; }
}
The Setup() for A() runs fine. However when Setup() is called for B(), I get this error:
NSubstitute.Exceptions.UnexpectedArgumentMatcherException : Argument
matchers (Arg.Is, Arg.Any) should only be used in place of member
arguments. Do not use in a Returns() statement or anywhere else
outside of a member call. Correct use:
sub.MyMethod(Arg.Any()).Returns("hi") Incorrect use:
sub.MyMethod("hi").Returns(Arg.Any())
This only happens when I run both tests by running all tests in that class.
If I run B() by itself, the Exception is not thrown.
Why does Setup() for B() fail only when run automatically after A()?
(nb. both tests are identical).
I'm using NUnit v3.8.1 and NSubstitute v2.0.3
I can do this with StructureMap using Constructor Injection. However I cannot find a way to do this with Simple Injector. Here is some code that illustrates this (sorry for the length)
I've looked at the lambda in the Register method, but can't seem to understand how to call a single application wide instance of the container to get the one instance I need.
These are the object graphs I wish to construct:
var bannerTalker =
new LoudMouth(
new ConsoleShouter(), // Implements IConsoleVoicer
new ObnoxiousBannerGenerator());
var plainTalker =
new TimidSpeaker(
new ConsoleWhisperer()); // Implements IConsoleVoicer
Here's the code:
``` c#
public interface IConsoleVoicer
{
void SaySomething(string whatToSay);
}
public class ConsoleWhisperer : IConsoleVoicer
{
public void SaySomething(string whatToSay)
{
Console.WriteLine(whatToSay?.ToLower());
}
}
public class ConsoleShouter : IConsoleVoicer
{
public void SaySomething(string whatToSay)
{
Console.WriteLine(whatToSay?.ToUpper());
}
}
public interface IBannerGenerator
{
string GetBanner();
}
public class ObnoxiousBannerGenerator : IBannerGenerator
{
public string GetBanner()
{
return "OBNOXIOUS";
}
}
public interface IBannerTalker
{
void SayWithBanner(string somethingToSay);
}
public class LoudMouth : IBannerTalker
{
private IConsoleVoicer Voicer { get; set; }
private IBannerGenerator BannerGenerator { get; set; }
public LoudMouth(
IConsoleVoicer concoleVoicer, IBannerGenerator bannerGenerator)
{
Voicer = concoleVoicer;
BannerGenerator = bannerGenerator;
}
public void SayWithBanner(string somethingToSay)
{
Voicer.SaySomething(string.Format("{0}:{1}",
BannerGenerator.GetBanner(), somethingToSay));
}
}
public interface IPlainTalker
{
void SayIt(string somethingToSay);
}
public class TimidSpeaker : IPlainTalker
{
private IConsoleVoicer Voicer { get; set; }
public TimidSpeaker(IConsoleVoicer concoleVoicer)
{
Voicer = concoleVoicer;
}
public void SayIt(string somethingToSay)
{
Voicer.SaySomething(somethingToSay);
}
}
And this is what I've tried:
static void Main(string[] args)
{
var container = new Container();
container.Register<IBannerGenerator, ObnoxiousBannerGenerator>();
container.Register<IPlainTalker, TimidSpeaker>();
container.Register<IBannerTalker, LoudMouth>();
//HERE IS THE DILEMMA! How do I assign
// to IBannerTalker a A LoudMouth contructed with a ConsoleShouter,
// and to IPlainTalkerTalker a A TimidSpeaker contructed with a ConsoleWhisperer
//container.Register<IConsoleVoicer, ConsoleShouter>();
container.Register<IConsoleVoicer, ConsoleWhisperer>();
var bannerTalker = container.GetInstance<IBannerTalker>();
var plainTalker = container.GetInstance<IPlainTalker>();
bannerTalker.SayWithBanner("i am a jerk");
plainTalker.SayIt("people like me");
}
Ric .Net is right in pointing you at the RegisterConditional methods. The following registrations complete your quest:
container.Register<IBannerGenerator, ObnoxiousBannerGenerator>();
container.Register<IPlainTalker, TimidSpeaker>();
container.Register<IBannerTalker, LoudMouth>();
container.RegisterConditional<IConsoleVoicer, ConsoleShouter>(
c => c.Consumer.ImplementationType == typeof(LoudMouth));
container.RegisterConditional<IConsoleVoicer, ConsoleWhisperer>(
c => c.Consumer.ImplementationType == typeof(TimidSpeaker));
The below code does what I would like it to do. The code in the Main method looks and behaves exactly as desired. However, it would be preferable if the class UserMenu, Home and DropdownMenu2 could only be used by the HeaderNavigationMenu to protect other developers from trying to used them outside of the HeaderNavigationMenu class. Additionally most articles frown upon making everything public.
Question:
Is the design patter being used below appropriate or is there something better and more acceptable to use in this scenario?
Edit: The reason for this design.
I wanted the end user of HeaderNavigationMenu to just be able to use the dot notation to get a list of available options. This Architecture accomplishes this goal (ex: navigationMenu.DropdownMenu2.SelectOption3())
Wanted anyone else who eventually might need to edit the code to understand that the classes UserMenu, Home and DropDownMenu2 where very specifically designed to be implemented by HeaderNavigationMenu class.
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenu();
Home = new Home();
DropdownMenu2 = new DropdownMenu2();
}
public UsersMenu UsersMenu { get; set; }
public Home Home { get; set; }
public DropdownMenu2 DropdownMenu2 { get; set; }
}
public class UsersMenu
{
...
}
public class Home
{
...
}
public class DropdownMenu2
{
public void SelectOption3()
{
...
}
...
}
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
Home home = new Home();
}
Restrict access to the class constructors. If they are declared as "internal" then the classes may only be created by your code.
If you're looking to protect against the instantiation of UsersMenu, DropdownMenu2, and Home from outside HeaderNavigationMenu but still within the same project as HeaderNavigationMenu then there is a neat trick that can achieve this behavior. You can use public nested classes with private constructors which statically initialize their own factory methods. The basic template for this would be:
public class Outer{
private static Func<Inner> _innerFactory;
public Inner ExposedInner {get; private set;}
public Outer(){
// Force the static initializer to run.
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Inner).TypeHandle);
// Call the newly created factory method instead of a regular constructor.
ExposedInner = _innerFactory();
}
public class Inner {
static Inner(){
// Initialize Outer's static factory method.
_innerFactory = () => new Inner();
}
// Inner cannot be instantiated (without reflection) because its constructor is private.
private Inner(){}
// This method is now exposed for anyone to use.
public void DoStuff(){ Console.WriteLine("Did stuff"); }
}
}
Here's this concept implemented in your example:
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// This line will no longer work because the constructors
// for the inner classes are private.
HeaderNavigationMenu.HomeImpl home = new HeaderNavigationMenu.HomeImpl();
Console.ReadKey();
}
}
public class HeaderNavigationMenu
{
//Private factory methods that are statically initialized
private static Func<UsersMenuImpl> _createUsers;
private static Func<DropdownMenu2Impl> _createDropdown;
private static Func<HomeImpl> _createHome;
public HeaderNavigationMenu()
{
//Force the static constructors to run
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(UsersMenuImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(HomeImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DropdownMenu2Impl).TypeHandle);
UsersMenu = _createUsers();
Home = _createHome();
DropdownMenu2 = _createDropdown();
}
public UsersMenuImpl UsersMenu { get; set; }
public HomeImpl Home { get; set; }
public DropdownMenu2Impl DropdownMenu2 { get; set; }
public class UsersMenuImpl
{
//Static constructor to make the class factory method
static UsersMenuImpl()
{
_createUsers = () => new UsersMenuImpl();
}
private UsersMenuImpl() { }
}
public class HomeImpl
{
//Static constructor to make the class factory method
static HomeImpl()
{
_createHome = () => new HomeImpl();
}
private HomeImpl() { }
}
public class DropdownMenu2Impl
{
//Static constructor to make the class factory method
static DropdownMenu2Impl()
{
_createDropdown = () => new DropdownMenu2Impl();
}
private DropdownMenu2Impl() { }
public void SelectOption3()
{
}
}
}
With this, you will still be able to use all the public properties of the inner classes however no one will be able to instantiate the inner classes from outside HeaderNavigationMenu and only HeaderNavigationMenu has access to the factory methods.
I don't really understand what your use case is and I've never coded like this but one way of only exposing the required behaviour of HeaderNavigationMenu would be to make the classes internal and the variables private and then expose only the SelectOption3() method, as below.
If you uncomment the line
//Home home = new Home();
you will get a compiler error.
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
//Home home = new Home();
}
}
public class HeaderNavigationMenu
{
UsersMenu usersMenu;
Home home;
DropdownMenu2 dropdownMenu2;
public HeaderNavigationMenu()
{
usersMenu = new UsersMenu();
home = new Home();
dropdownMenu2 = new DropdownMenu2();
}
public void DropdownMenu2SelectOption3()
{
dropdownMenu2.SelectOption3();
}
class UsersMenu
{
}
class Home
{
}
class DropdownMenu2
{
public void SelectOption3()
{
}
}
}
You could make UsersMenu, Home, and DropdownMenu2 public abstract classes. Then have private classes nested inside of HeaderNavigationMenu which extend the public abstract versions.
public abstract class UsersMenu
{
}
public abstract class Home
{
}
public abstract class DropdownMenu2
{
public void SelectOption3()
{
// Code for SelectOption3...
}
}
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenuImpl();
Home = new HomeImpl();
DropdownMenu2 = new DropdownMenu2Impl();
}
public UsersMenu UsersMenu { get; }
public Home Home { get; }
public DropdownMenu2 DropdownMenu2 { get; }
private class UsersMenuImpl : UsersMenu
{
}
private class HomeImpl : Home
{
}
private class DropdownMenu2Impl : DropdownMenu2
{
}
}
Fellow developers can see and use the UsersMenu, Home, and DropdownMenu2 abstract classes, but cannot create instances of them. Only HeaderNavigationMenu can.
Of course, another developer could always create their own classes deriving from the public abstract ones, but there is only so much you can do. UsersMenu, Home, and DropdownMenu2 have to be public in order to be public properties.
I have an abstract class that I want to test. There is an abstract property in this class for my DAO, which I define in inherited classes.
public abstract class DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup
{
protected abstract IDeviceGroupDao<TDeviceGroup> DeviceGroupDao { get; }
public TDeviceGroup UpdateDeviceIndexes(Device device)
{
return DeviceGroupDao.GetDeviceGroup(device.Group.Id);
}
}
I want to test the Updatedeviceindexes method so I'm trying to mock a property called DeviceGroupDao.
[TestFixture]
[Category("Unit")]
public class DeviceGroupManagerBaseTests
{
private IFixture fixture;
private Mock<DeviceGroupManagerBase<DeviceGroup>> subject;
private Mock<IDeviceGroupDao<DeviceGroup>> deviceGroupDaoMock;
private DeviceGroupManagerBase<DeviceGroup> Manager => subject.Object;
[TestFixtureSetUp]
public void Init()
{
fixture = new Fixture().Customize(new AutoMoqCustomization());
deviceGroupDaoMock = fixture.Freeze<Mock<IDeviceGroupDao<DeviceGroup>>>();
subject = fixture.Freeze<Mock<DeviceGroupManagerBase<DeviceGroup>>>();
}
[Test]
public void TestUpdateDeviceIndexes()
{
var device = fixture.Create<Device>();
var deviceGroup = fixture.Create<DeviceGroup>();
deviceGroupDaoMock.Setup(x => x.GetDeviceGroup(It.IsAny<int>())).Returns(deviceGroup);
var result = Manager.UpdateDeviceIndexes(device);
// The resultDeviceGroup will not be contain a previously defined object
Assert.AreEqual(deviceGroup.Id, result.Id);
}
}
I also tried to add registration for my device object in this way:
fixture.Register(() => deviceGroup);
But I'm still getting a new object.
How can I mock IDeviceGroupDao<TDeviceGroup>?
Since DeviceGroupManagerBase is an abstract base class, you'll need a SUT Double. It's easiest to do if you make the DeviceGroupDao property public:
public abstract class DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup
{
public abstract IDeviceGroupDao<TDeviceGroup> DeviceGroupDao { get; }
public TDeviceGroup UpdateDeviceIndexes(Device device)
{
return DeviceGroupDao.GetDeviceGroup(device.Group.Id);
}
}
Otherwise, you'll need to use Moq's API for defining and overriding protected members, which is possible, but more work.
Then you'll need to override subject's DeviceGroupDao property:
subject.SetupGet(x => x.DeviceGroupDao).Returns(deviceGroupDaoMock.Object);
Here's the full test:
[TestFixture]
[Category("Unit")]
public class DeviceGroupManagerBaseTests
{
private IFixture fixture;
private Mock<DeviceGroupManagerBase<DeviceGroup>> subject;
private Mock<IDeviceGroupDao<DeviceGroup>> deviceGroupDaoMock;
private DeviceGroupManagerBase<DeviceGroup> Manager => subject.Object;
[OneTimeSetUp]
public void Init()
{
fixture = new Fixture().Customize(new AutoMoqCustomization());
deviceGroupDaoMock = fixture.Freeze<Mock<IDeviceGroupDao<DeviceGroup>>>();
subject = fixture.Freeze<Mock<DeviceGroupManagerBase<DeviceGroup>>>();
subject.SetupGet(x => x.DeviceGroupDao).Returns(deviceGroupDaoMock.Object);
}
[Test]
public void TestUpdateDeviceIndexes()
{
var device = fixture.Create<Device>();
var deviceGroup = fixture.Create<DeviceGroup>();
deviceGroupDaoMock.Setup(x => x.GetDeviceGroup(It.IsAny<int>())).Returns(deviceGroup);
var result = Manager.UpdateDeviceIndexes(device);
Assert.AreEqual(deviceGroup.Id, result.Id);
}
}
This now passes on my machine.
Because the DeviceGroupDao is protected you will need to find a way to access it externally. Create a stub that would allow you set it value.
public class DeviceGroupManagerBaseStub<TDeviceGroup>
: DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup {
private IDeviceGroupDao<TDeviceGroup> deviceGroupDao;
public DeviceGroupManagerBaseStub(IDeviceGroupDao<TDeviceGroup> deviceGroupDao) {
this.deviceGroupDao = deviceGroupDao;
}
protected override IDeviceGroupDao<TDeviceGroup> DeviceGroupDao {
get {
return deviceGroupDao;
}
}
}
You can then mock IDeviceGroupDao<TDeviceGroup> and inject it into the stub for your test.
I am creating an application in ASP.NET web form with MVP pattern. I am getting some issues working with TDD. I have created two test, one is working fine but when a second test is executed it throws an error.
Below is my declared View
public interface IAddUpdateView : IView
{
string Type { get; set; }
string PageTitle { set; }
string Details { get; set; }
bool Active { get; set; }
}
Presenter
// BasePresenter is an abstract class contains abstract method with name Initialize()
public class MyPresenter: BasePresenter<IAddUpdateView >
{
private readonly IDatabaseLayer _databaselayer;
public MyPresenter(IAddUpdateView view, IDatabaseLayer databaseLayer) : base(view)
{
_databaselayer = databaseLayer;
}
public override void Initialize()
{ }
public void Initialize(string str)
{
string[] str1=Misc.DecryptURL(str);
View.Type = str1[0].ToString(); // ERROR LINE
if (View.Type.ToLower().Trim() == "add")
{
View.PageTitle = "Add New Task";
}
else if (View.Type.ToLower().Trim() == "edit")
{
}
}
}
Now I am working on creating unit test mocking the Presenter class to test the dependencies using Rhino mocks.
That's my test class with just two test methods. These test methods test when loading a View it calls appropriate Page Type.
When ADD type is called, it get the View.Type as "add" and when Edit type is called, it verifies for the specific object that is loaded.
[TestFixture]
public class MyPresenterTest
{
private IAddUpdateView _view;
private MyPresernter _controller;
[SetUp]
public void SetUp()
{
_view = MockRepository.GenerateMock<IAddUpdateView >();
_controller = new MyPresernter (_view, MockDataLayer());
}
[TearDown]
public void TearDown() { _controller = null; _view = null; }
// TEST 1
[Test]
public void When_Loading_for_Add_View_Panel_Return_Type_Add()
{
// Arrange
_view.Stub(x => x.Type).PropertyBehavior();
//Act
_controller.Initialize(GetURLWithAddValue());
// GetURLWithAddValue: This method get the URL with querystring contains value as "add"
//Assert
Assert.AreEqual("add",_view.Type);
}
TEST 2
// When this test method is run, It has the Type="edit", but in my
presenter View.Type (see LINE ERROR), my Type is null even I
assigned the values.
[Test]
public void When_Loading_for_Edit_View_Panel_Load_Correct_Object()
{
// Arrange
_view.Stub(x =>x.TaskDetails).PropertyBehavior();
//Act
Task o=new Task(){ TaskId=6, TASK_NAME="Task 6"};
_controller.Initialize(GetURLWithEditValue(o));
//Assert
Assert.AreEqual(o.TASK_NAME, _view.TaskDetails);
}
private static IDatabaseLayer MockDataLayer()
{
IDatabaseLayer obj = MockRepository.GenerateMock<IDatabaseLayer>();
MockTaskDataLayer a = new MockTaskDataLayer();
obj.Stub(x => x.GetList());
return obj;
}
}
Can someone guide me why Test 1 get passed and when Test 2 is executed, after assigning a value in View.Type (see LINE ERROR in MyPresenter class) it's still null??
Thanks,