hopefully it's pretty simple but I'm stuck trying to figure this out.
If I have a simple class with a method which is supposed to do something and then show a messagebox via MessageBox.Show("") when some values are in a certain state, how do I write a test/tests that can detect if a the messagebox was shown when expected and/or not shown when not expected?
You can't really test that though Unit tests. There is an easy way to test if the code was called correctly though.
I would hide showing the MessageBox behind an interface. Then mock that interface and create a counter or something like that in your mock implementation. Of course you can make this as specific as you need, providing the message shown, etc.
You shouldn't test that a MesssageBox appears, though it is possible to do so with one or another UI automation framework (like https://msdn.microsoft.com/en-us/library/ms747327(v=vs.110).aspx).
But it won't be a unittest. It would be an automated UI test.
So, if you want to create a proper unittest, then your class should be injectable with some
public interface IMessageBox
{
void Show(String message);
}
public class SUT
{
public SUT(IMessageBox messageBox)
{
this._messageBox = messageBox;
}
public void Test()
{
this._messageBox.Show("TEST);
}
}
So that you can mock that IMessageBox inside the unittest.
For example, with Moq:
[TestMethod]
public void Test()
{
// Arrange
var messageBox = new Mock<IMessageBox>();
messageBox
.Setup(m =>
m.Show("TEST))
.Verifiable();
var sut = new SUT(messageBox.Object);
// Act
sut.Test();
// Verify
messageBox.Verify();
}
Related
I have a logger class, which purpose is to be called from whatever class in my solution, who decides to log something.
I added an interface, which is why I applied a singleton pattern, and didn't use a static class.
My LogManager implementation (singleton):
https://pastebin.com/NHKmbj9c
I wanted to write simple unit tests, which are supposed to use local variables, testing the functionality of each ILogger methods, but as soon as my first Unit has passed, the Singleton will stay initialized in context, making subsequent unit tests to fail (while they are trying to Initialize the singleton...).
Unit Test:
[TestClass]
public class LogManagerTests
{
[TestMethod]
public void Error_ExpectedErrorLevel_ShouldBe_Error()
{
// Arrange
var actualLevel = ErrorLevel.Warning;
const ErrorLevel expectedLevel = ErrorLevel.Error;
var iLogger = LogManager.GetInstance;
iLogger.Initialize((level, msg) => { actualLevel = level; }, null);
// Act
iLogger.Error(new Exception(), string.Empty);
// Assert
Assert.AreEqual(expectedLevel, actualLevel);
}
[TestMethod]
public void Debug_ExpectedErrorLevel_ShouldBe_Verbose()
{
// Arrange
var actualLevel = ErrorLevel.Warning;
const ErrorLevel expectedLevel = ErrorLevel.Verbose;
var iLogger = LogManager.GetInstance;
iLogger.Initialize(null, (level, msg, ex) => { actualLevel = level; });
// Act
iLogger.Debug(string.Empty);
// Assert
Assert.AreEqual(expectedLevel, actualLevel);
}
}
Another tought is to initialize the LogManager as a private global variable within my TestClass, but this could give race conditions if the Unit test runs async, as multiple methods then will access the same output variable, which may override each others.
Is it possible to UnitTest a singleton in any way?
The design does not allow me to refactor the LogManager, and remove the singleton pattern from it.
It's possible to unit test a singleton, you just need to think about it differently. Don't try so hard to change your methodology to fit the test. Think about creating a method that is used only for testing, LogManager.Uninitialize().
Call this after every test in this group of tests to ensure your singleton is set back to a testable state.
[TestCleanup()]
public void Cleanup()
{
LogManager.Uninitialize();
}
It may not be pure but I think it's fine to write in a diagnostics method every once in a while. It's better than having bad test coverage where you need good test coverage.
I've done extensive research on this topic and have yet to find a reliable answer so here goes.
I have a constructor I'd like to test. This constructor initializes another class in order to set a global variable which is necessary throughout the rest of the class. However, the constructor of the class which the constructor initializes has dependencies on things like web session and other variables being set which are not set when the any tests run. How can I properly mock this to make sure I'm just testing the constructor?
Here's the constructor to be tested:
public CheckoutManager()
{
_orderController = new OrderController();
_orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
The problem lies in the OrderController constructor:
public OrderController()
{
_customer = WebUserSession.Current.Profile.Customer;
_srd = ContextManager.GetStandardRequestByCulture( CultureInfo.CurrentUICulture.Name );
WarehouseData data = new WarehouseData();
data.WarehouseID = 0; // TODO: Convert the 0 warehouse to a web warehouse type
// Grab the attention items from the session
AttentionItems = WebUserSession.Current.OrderAttentionItems;
// Load the shopping cart
_cart = ShoppingCartManager.Cart;
}
Here is my attempted test:
[TestMethod]
public void Constructor_ExpectInstantiation()
{
var checkoutManager = new CheckoutManager();
Assert.IsNotNull( checkoutManager );
}
It bombs out at the _customer = WebUserSession.Current.Profile.Customer; line. How do you mock this using Moq? If it cannot be mocked, is there a good explanation as to why? How could the original constructor be modified to have the same functionality in a more testable way? Thank you in advance.
You can use Dependency Injection, which is a form of Inversion of Control, to solve these kind of problems.
Instead of instantiating your OrderController in the constructor, pass it as an argument:
public CheckoutManager(OrderController orderController)
{
_orderController = orderController;
_orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
You can then either instantiate the OrderController either manually somewhere in a Main-like method, or with a library like Autofac which will do all the wiring for you.
So now you can mock your interface in your test:
[TestMethod]
public void Constructor_ExpectInstantiation()
{
Mock<OrderController> mockOrderController = new Mock<OrderControler>();
var checkoutManager = new CheckoutManager(mockOrderController.Object);
Assert.IsNotNull( checkoutManager );
}
That way, the constructor of OrderController will never be called (it's a mock) and it won't interfere with your tests of CheckoutManager. If you need to test some interactions with it, you can Setup and Verify specific methods using Moq.
You won't be able to use Moq test to this code. You could
Modify the code to make it more testable by adding a constructor that accepts an OrderController
Use a more "advanced" testing technique such as shims.
Background
I need some class to perform background initialization, which should start in constructor. Currently I'm using a Task which is started by constructor, and then all operations, depending on that initialization wait for that Task completion.
Please take a look at the following simplified example:
interface IEntry {}
interface IRepository
{
IQueryable<IEntry> Query { get; }
void Add(IEntry entry);
}
class PrefetchedRepository : IRepository
{
private readonly Task _prefetchingTask;
private readonly ICollection<IEntry> _entries = new List<IEntry>();
private readonly IRepository _underlyingRepository;
public PrefetchedRepository(IRepository underlyingRepository)
{
_underlyingRepository = underlyingRepository;
// Background initialization starts here
_prefetchingTask = Task.Factory.StartNew(Prefetch);
}
public IQueryable<IEntry> Query
{
get
{
EnsurePrefetchCompleted();
return _entries.AsQueryable();
}
}
public void Add(IEntry entry)
{
EnsurePrefetchCompleted();
_entries.Add(entry);
_underlyingRepository.Add(entry);
}
private void EnsurePrefetchCompleted()
{
_prefetchingTask.Wait();
}
private void Prefetch()
{
foreach (var entry in _underlyingRepository.Query)
{
_entries.Add(entry);
}
}
}
This works. The problem starts when I want to test initialization in Unit Test. I'm creating the instance and providing the mock of underlying repository. I want to ensure that all entries were fetched from the mock as expected.
[TestFixture]
public class PrefetchingRepositoryTests
{
[Test]
public void WhenInitialized_PrefetchingIsDone()
{
// Arrange
var underlyingRepositoryMock = A.Fake<IRepository>();
// Act
var target = new PrefetchedRepository(_underlyingRepository);
// Assert
underlyingRepositoryMock.CallsTo(r => r.Query).MustHaveHappened(Repeated.Exactly(1));
}
}
As you can imagine, most of the time fails, because actually initialization didn't started yet at the assertion point.
Questions
Question 1 - Initialization: Is there more elegant way of asynchronous initialization rather than starting task in constructor and waiting for it in all dependent operations?
Question 2 - Testing: I thought of 2 possible ways to solve race between the test and testee:
Using event handle to the test:
[Test]
public void WhenInitialized_PrefetchingIsDone()
{
// Arrange ...
var invokedEvent = new ManualResetEvent(false);
underlyingRepositoryMock.CallsTo(r => r.Query).Invokes(_ => invokedEvent.Set());
// Act ...
// Assert
Assert.True(invokedEvent.WaitOne(1000));
}
Exposing EnsurePrefetchCompleted method as internal and using it in the Unit Test (assuming usage of [assembly: InternalsVisibleTo("...")])
The problem with both solutions is that in case of failure time duration long (actually in the second case - it is limited by test timeout).
Is there any simpler way to do this kind of testing?
Extract the prefetch logic into a separate Prefetcher class and when testing mock the Prefetcher with something that does the fetching without the use of a separate thread.
This will allow you to do the white-box testing of your PrefetchedRepository which I see you are attempting to do with
underlyingRepositoryMock.CallsTo(r => r.Query).MustHaveHappened(Repeated.Exactly(1)); (I would never do white-box testing, but that's just me.)
Once you are done with your white box testing, you can then do black-box testing of your PrefetchedRepository, without concern as to how it works internally. (Whether it invokes other objects to do its job, how many times it invokes them, etc.) Therefore, your testing code will not need to guess the point in time when it is okay to check whether query has been invoked, because it will not be concerned at all with whether query was invoked or not. Essentially, your testing code will be testing against interface IRepository, not against class PrefetchedRepository.
Don't expose a instance which is in invalid state. Client code may often notice a delay when calling any members in PrefetchedRepository just because the underlying repository is slow. You're trying to be clever by hiding these details by hiding all the grotty waiting logic inside EnsurePrefetchCompleted which client code doesn't even know. But this may surprise the client why does even this takes a lot of time??
Better approach is to expose the Task in the public surface of the API and let the client code await it before it does anything with the repository instance.
Something like this:
class PrefetchedRepository : IRepository
{
private readonly Task _prefetchingTask;
private readonly ICollection<IEntry> _entries = new List<IEntry>();
private readonly IRepository _underlyingRepository;
public PrefetchedRepository(IRepository underlyingRepository)
{
_underlyingRepository = underlyingRepository;
// Background initialization starts here
_prefetchingTask = Task.Factory.StartNew(Prefetch);
}
public Task Initialization
{
get
{
return _prefetchingTask;
}
}
...
}
Then you could do
var repo = new PrefetchedRepository(someOtherSlowRepo);
await repo.Initialization;
//Then do whatever with the repo.
Of course delete that EnsurePrefetchCompleted method and all calls to it.
But I do understand this introduces the smell so-called Temporal Coupling.
Better design is to introduce a Factory which does this for you.
public class PrefetchedRepositoryFactory
{
public Task<IRepository> CreateAsync()
{
//someOtherSlowRepo can be a parameter or instance field of this class
var repo = new PrefetchedRepository(someOtherSlowRepo);
await repo.Initialization;
return repo;
}
}
Then you could simply do
var repo = await prefetchedRepositoryFactory.CreateAsync();
//Do whatever with repo.
If you do so, you don't have to take any special care for testing as you'll always have the fully constructed repository in hand.
You can await inside the Test methods; Most of the major unittesting frameworks supports async Task returning methods.
Is there a way or approach like a method decorator or attribute for a test method that can say for example:
"Run Method C Before running Method B"
So basically you are creating a dependancy between C and B. I know tests are better off being atomic and should be but sometimes in it's better to keep your tests small and to the point. It makes sense not run a 'RemoveItem' test method when the item it is looking for is simply not there.
Most people would add the item before hand and then test to see if they can remove - 'All In the same test'. I don't like this approach and want to make my tests smaller, more to to point and more atomic as possible.
Like you said, you dont want interdependencies between your test. If you are not comfortable having an "Add" before the "Remove" in your remove test, thus testing the Add method in the wrong place, then I recommend using testInitialize to setup some objects the tests can act on. I do however recommend the practice of actually running Add before you run Remove, in the test of Remove.
[Testclass]
public class TestStacks
{
private Stack<string> emptyStack;
private Stack<string> singleItemStack;
[TestInitialize]
public void Setup()
{
singleItemStack = new Stack<string>();
singleItemStack.Push("Item");
emptyStack = new Stack<string>();
}
[TestMethod]
public void TestPush()
{
emptyStack.Push("Added");
Assert.AreEqual(1, emptyStack.Count);
}
[TestMethod]
public void TestRemove()
{
singleItemStack.Pop();
Assert.AreEqual(0, singleItemStack.Count);
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void TestPopFromEmpty()
{
emptyStack.Pop();
}
}
If you need to have some item added before testing removal, then best place to add item is arrange part of removal test. This will make context of removal test clear.
But DRY principle also works here - you can move addition logic to separate helper method. Then call it twice - when testing addition, and when arranging context for removal:
[Testclass]
public class Tests
{
[TestMethod]
public void TestAddition()
{
AddItem();
// Assert addition
}
[TestMethod]
public void TestRemoval()
{
AddItem();
// Remove item
// Assert removal
}
private void AddItem()
{
// Add item
}
}
I need some assistance with writing a unit test for the following class using Rhino Mocks 3.5. The following overrided method in my class:
public override void Initialize(params object[] messages)
{
var data = new ViewData
{
Name = this.GetName()
};
this.Notify(data);
}
I want to be write a test to validate that when the Initialize method is called, the method calls the Notify method and has a parameter of type ViewData. Also I want to check that the GetName method which is a private method is called within this method. I use an accessor to access the GetName private method.
Any help would be great with this as I am new to writing tests and need assistance.
What you want is called a partial mock.
[Test]
public void UsingPartialMocks()
{
MockRepository mocks = new MockRepository();
YourClass partialMock = mocks.PartialMock<YourClass>();
Expect.Call(partialMock.Notify(null)).IgnoreArguments();
mocks.ReplayAll();
partialMock.Initialize(null);
mocks.VerifyAll();
}
While not directly answering your question on how to do it using Rhino (it appears that Jon has done a decent job at that already), for posterity sake I'll show how I would test it using manual mocking. (bear with me, it's been a while since I've done C#, so pardon the syntax errors)
[Test]
public void initializeRegistersViewDataWithGivenName()
{
ShuntedYourClass yourClass = new ShuntedYourClass();
yourClass.initialize( /* arg list */ );
// Verify 'Notify' was called
Assert.NotNull(yourClass.registeredViewData);
// Verify 'GetName' private method was invoked and
// 'Name' was properly populated
Assert.AreEqual("expected name", yourClass.registeredViewData.Name);
}
// Nested class for testing purposes only.
class ShuntedYourClass : public YourClass
{
public ViewData registeredViewData;
public override void Notify(ViewData vd)
{
this.registeredViewData = vd;
}
}
This code now verifies that the Initialize method does indeed work properly and executes the Notify with the proper parameters.
Hope that helps!
Brandon