Rhino Mock, Mock list of interface - c#

How can i Mock list of object in for loop
Here is the code:`
public class SearchResult<T>
{
private readonly ISearcher<T> _searcher;
private readonly IList<ISearchConfigurator> _configurators;
public SearchResult(ISearcher<T> searcher, IList<ISearchConfigurator> configurators)
{
_searcher = searcher;
_configurators = configurators;
}
public DomainSearchResult<T> FindInAllDomains()
{
DomainSearchResult domainSearchResults = new DomainSearchResult<T>();
foreach (var configurator in _configurators)
{
IList<T> results = _searcher.SearchAll(configurator);
domainSearchResults.Results.Add(_configurator.DomainName, results);
}
return domainSearchResults;
}
}`
the property result is declared in the DomainSearchResult class :
IDictionary<string,IList<T>> Results { get; set; }
then i tried the following:
[Test]
public void FindInAllDomains_ReturnsAllRecord()
{
//Arrange
var configuratorMock = MockRepository.GenerateStub<IList<ISearchConfigurator>>();
var searchMock = MockRepository.GenerateMock<ISearcher<NativeDs>>();
var searchRestul = new SearchResult<NativeDs>(searchMock, configuratorMock);
//Act
searchRestul.FindInAllDomains(); // calling test fail here
//Assert
searchMock.AssertWasCalled(x => x.SearchAll(null), opt => opt.IgnoreArguments());
}
Error is:
System.NullReferenceException : Object reference not set to an instance of an object.

Try this...
var list = new List<ISearchConfigurator>
(from x in Enumerable.Range(1, 100)
select MockRepository.GenerateMock<ISearchConfigurator>()
);

Related

Unit test singletons

I have a singleton class and I want to run some unit tests in isolation. The problem is that all the tests run on the same instance and affect the expected results. Is there a workaround? I am using .net 6 and NUnit 3. Here's my code,
public interface ISingletonModel<T>
{
void AddValue(string key, T value, LinkedListNode node);
}
public sealed class SingletonModel<T> : ISingletonModel<T>
{
public Dictionary<string, (LinkedListNode<string> node, T value)> ModelDictionary { get; set; }
private static readonly Lazy<SingletonModel<T>> singletonModel=
new Lazy<SingletonModel<T>>(() => new SingletonModel<T>());
public static SingletonModel<T> Instance
{
get
{
return SingletonModel.Value;
}
}
private SingletonModel()
{
ModelDictionary = new Dictionary<string, (node, T value)>();
}
}
public void AddValue(string key, T value, LinkedListNode node)
{
if (ModelDictionary.ContainsKey(key))
{
var linkedListNode = ModelDictionary[key];
ModelDictionary[key] = (node, value);
}
else
{
ModelDictionary.Add(key, (node.AddFirst(key), value));
}
}
}
And some unit tests
private TestClass[] testData;
private IFixture fixture;
private SingletonModel<TestClass> model;
[SetUp]
public void Setup()
{
this.testData = GenerateTestData();
this.model= SingletonModel<TestClass>.Instance;
}
[Test]
public void CheckModelCapacity_ShouldReturnTheCorrectItems()
{
/ Act
foreach (var entity in testData)
{
this.model.AddValue(entity.Id, entity, entity.node);
}
IEnumerable<string> expected = new[] { "8", "3", "5", "2", "79" };
var actual = this.model.ModelDictionary.Keys.ToList();
// Assert
Assert.That(expected.OrderBy(x => x).SequenceEqual(actual.OrderBy(x => x)));
}
[Test]
public void CheckTotalItems_ShouldReplaceItemsWithTheSameKey()
{
// Assign
var entity1 = fixture.CreateMany(20);
// Act
foreach (var item in entity1)
{
this.model.AddValue(item.Id, item, item.node);
}
//Assert
Assert.AreEqual(2, this.model.ModelDictionary.Count);
}
Because of the singleton the tests are holding the values from the previous tests.
A public or internal constructor would allow for creating isolated instances in tests, but if the intention here is to not modify the current class then reflection can be used to access the private constructor to create isolated instances for tests.
Here is a simplified model based on the original since it was incomplete and wouldn't compile.
public interface ISingletonModel<T> {
void AddValue(string key, T value);
int Count { get; }
}
public sealed class SingletonModel<T> : ISingletonModel<T> {
Dictionary<string, T> dictionary;
private static readonly Lazy<SingletonModel<T>> singletonModel = new Lazy<SingletonModel<T>>(() => new SingletonModel<T>());
public static SingletonModel<T> Instance => singletonModel.Value;
private SingletonModel() {
dictionary = new Dictionary<string, T>();
}
public void AddValue(string key, T value) => dictionary[key] = value;
public int Count => dictionary.Count;
}
Using one of the overloads of Activator.CreateInstance:
Activator.CreateInstance(Type type, bool nonPublic)
which uses reflection to access the private constructor, shows that instances can be created to be tested in isolation
public class Program {
public static void Main() {
//Arrange
int expected = 1;
ISingletonModel<int> model1 = (ISingletonModel<int>)Activator.CreateInstance(typeof(SingletonModel<int>), true);
//Act
model1.AddValue("one", 1);
//Assert
int actual = model1.Count;
Console.WriteLine($"{actual}, As expected: {actual == expected}");
//Arrange
expected = 3;
ISingletonModel<int> model2 = (ISingletonModel<int>)Activator.CreateInstance(typeof(SingletonModel<int>), true);
//Act
model2.AddValue("one", 1);
model2.AddValue("two", 2);
model2.AddValue("three", 3);
//Assert
actual = model2.Count;
Console.WriteLine($"{actual}, As expected: {actual == expected}");
//Arrange
expected = 2;
ISingletonModel<int> model3 = (ISingletonModel<int>)Activator.CreateInstance(typeof(SingletonModel<int>), true);
//Act
model3.AddValue("one", 1);
model3.AddValue("two", 2);
//Assert
actual = model3.Count;
Console.WriteLine($"{actual}, As expected: {actual == expected}");
}
}
which return the following output
1, As expected: True
3, As expected: True
2, As expected: True
Add ResetForTesting() method your singleton class?

Moq Setup dont working, while trying to automate it

Main Goal : Automatic Moq an entire DBContext
Current Problem: Setup donĀ“t work. It runs and adds the Setup but when you try to access the Data you get an "NotImplemented Exception"
The member 'IQueryable.Provider' has not been implemented on type 'DbSet 1Proxy_4' which inherits from 'DbSet 1'. Test doubles for 'DbSet 1' must provide implementations of methods and properties that are used.
My class
public abstract class MoqBase<T> where T : DbContext
{
public Mock<T> MockContext { get; private set; }
public void Mock()
{
MockContext = new Mock<T> { DefaultValue = DefaultValue.Mock };
MockContext.SetupAllProperties();
PrepareContext();
}
private void PrepareContext()
{
var propertyList = MockContext.Object.GetType().GetProperties();
var tablePropertyList = propertyList.Where(x => x.PropertyType.FullName.Contains("DbSet")).ToList();
foreach (var tableProperty in tablePropertyList)
{
var proxy = tableProperty.GetValue(MockContext.Object);
dynamic mockSet = ((dynamic)proxy).Mock;
AddTableSetup(mockSet);
}
}
public void AddTableSetup<TTable>(Mock<DbSet<TTable>> Mockset) where TTable : class
{
var list = new List<TTable>();
var data = list.AsQueryable();
Mockset.As<IQueryable<TTable>>().Setup(m => m.Provider).Returns(data.Provider);
Mockset.As<IQueryable<TTable>>().Setup(m => m.Expression).Returns(data.Expression);
Mockset.As<IQueryable<TTable>>().Setup(m => m.ElementType).Returns(data.ElementType);
Mockset.As<IQueryable<TTable>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator);
}
}
TestMoq which implements MoqBase
public class TestMoq : MoqBase<NetConPortalContext>//NetConPortalContext is my dbContext
{
public TestMoq() => Mock();
}
Try to access
static void Main()
{
var moq = new TestMoq();
var context = moq.MockContext.Object;
var test = context.User.FirstOrDefault();
}
Picture of Error and Setup in Debug

Moq.Setup Expression of type 'System.Web.Mvc.ActionResult' cannot be used for return type 'System.Web.Mvc.ActionResult'

I'm working on some legacy code (def: untested code - some well designed some not) and trying to develop some tests to confirm recent changes did what they expected etc. I'm running into an issue where I'm trying to force a method that has a try{catch} block in it to throw an exception using Moq. When I try to run the test it fails during the mock.Setup call with System.ArgumentException "Expression of type 'System.Web.Mvc.ActionResult' cannot be used for return type 'System.Web.Mvc.ActionResult'".
The basic setup of the code:
Interface for FilterController...
public interface IFilterController
{
ActionResult DeleteFilter(string reportFilter, bool customReport = true);
}
FilterController class...
public class FilterController : BaseController, IFilterController
{
public FilterController(
IServiceFactory serviceFactory,
IAwsServiceFactory awsServiceFactory,
IReportServiceFactory reportServiceFactory,
IAzureServiceFactory azureServiceFactory)
: base(typeof(FilterController), serviceFactory, awsServiceFactory, reportServiceFactory, azureServiceFactory)
{
}
// method under test
public ActionResult (string reportFilter, bool customReport = true) {
try {
// NOTE: I have trimmed down the actual code in the try block significantly for brevity - I should be able to hook onto something here as a way to mock something throwing an exception
var customReportFilterService = _serviceFactory.CreateCustomReportFilterService();
var emailReportSettingService = _serviceFactory.CreateEmailReportSettingService();
string message = string.Empty;
JsonReturnType type = JsonReturnType.DisplayMessage; // an enum
var filter = customReportFilterService.GetReportFilterByHash(SessionHelper.User.CustomerId, reportFilter, initLinkedProjects: true);
return JsonActionResult(type, ajaxMessage: message, redirectTo: filter == null ? null : string.Format("Report/{0}", filter.ReportName));
}
catch (Exception ex)
{
return JsonActionResult(JsonReturnType.Error, ajaxMessage: "There was an error in deleting the filter.");
}
}
}
BaseController class...
public class BaseController : Controller
{
private readonly ProgressController _progressController;
protected IServiceFactory _serviceFactory;
protected IAwsServiceFactory _awsServiceFactory;
protected IReportServiceFactory _reportServiceFactory;
protected IAzureServiceFactory _azureServiceFactory;
protected IApplicationSettingService _applicationSettingService;
protected IReportMonitorService _reportMonitorService;
protected ISymmetricAlgorithmProvider HiddenEncrypter { get; set; }
private Stopwatch _watch;
private bool _timePageEnabled;
private bool _maintenance;
private int _pageLoadThreshold;
private readonly ILog Logger;
public BaseController(Type type, IServiceFactory serviceFactory, IAwsServiceFactory awsServiceFactory, IReportServiceFactory reportServiceFactory, IAzureServiceFactory azureServiceFactory)
{
Logger = LogManager.GetLogger(type);
_progressController = new ProgressController();
_serviceFactory = serviceFactory;
_awsServiceFactory = awsServiceFactory;
_reportServiceFactory = reportServiceFactory;
_azureServiceFactory = azureServiceFactory;
_applicationSettingService = _serviceFactory.CreateApplicationSettingService();
_reportMonitorService = _serviceFactory.CreateReportMonitorService();
_watch = new Stopwatch();
_timePageEnabled = _applicationSettingService.ReadApplicationSettingFromCache<bool>(CC.Data.Model.Constants.ApplicationSettings.CheckSlowPageLoad, true);
_pageLoadThreshold = _applicationSettingService.ReadApplicationSettingFromCache<int>(CC.Data.Model.Constants.ApplicationSettings.PageLoadThreshold, 120);
_maintenance = _applicationSettingService.MaintenanceMode();
}
// System.Web.Mvc.ActionResult type mentioned in error
public ActionResult JsonActionResult(JsonReturnType returnType, string view = null, string ajaxMessage = null, string redirectTo = null, string target = null, object data = null, string popupTitle = null)
{
if (returnType == JsonReturnType.LoadContent)
_progressController.CompleteProgressCache();
var serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
var resultData = new {
ReturnType = returnType,
HtmlView = view,
Message = ajaxMessage,
RedirectTo = redirectTo,
Target = target,
CustomData = data,
ProjectId = SessionHelper.ProjectId,
PopupTitle = popupTitle,
MaintenanceMode = _maintenance
};
ContentResult result;
result = new ContentResult
{
Content = serializer.Serialize(resultData),
ContentType = "application/json"
};
return result;
}
}
Controller class...
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter {
// stuff
}
Unit Test class...
[TestClass]
public class FilterControllerTest
{
private FilterController filterController;
private Mock<IFilterController> filterControllerMock;
private Mock<IServiceFactory> serviceFactoryMock;
private Mock<IAwsServiceFactory> awsServiceFactoryMock;
private Mock<IReportServiceFactory> reportServiceFactoryMock;
private Mock<IAzureServiceFactory> azureServiceFactoryMock;
private Mock<IApplicationSettingService> applicationSettingServiceMock;
[ClassInitialize]
public static void ClassInit(TestContext context)
{
}
[TestInitialize]
public void Initialize()
{
filterControllerMock = new Mock<IFilterController>();
serviceFactoryMock = new Mock<IServiceFactory>();
awsServiceFactoryMock = new Mock<IAwsServiceFactory>();
reportServiceFactoryMock = new Mock<IReportServiceFactory>();
azureServiceFactoryMock = new Mock<IAzureServiceFactory>();
applicationSettingServiceMock = new Mock<IApplicationSettingService>();
serviceFactoryMock
.Setup(s => s.CreateApplicationSettingService())
.Returns(applicationSettingServiceMock.Object);
filterController = new FilterController(
serviceFactoryMock.Object
, awsServiceFactoryMock.Object
, reportServiceFactoryMock.Object
, azureServiceFactoryMock.Object);
}
[TestCleanup]
public void Cleanup()
{
}
[ExpectedException(typeof(Exception))]
[TestMethod]
public void DeleteFilter_ExceptionThrown_IsCaughtAndLoggedAndReturnsActionResultOfError()
{
// Arrange
filterControllerMock
.Setup(x => x.DeleteFilter(It.IsAny<string>(), It.IsAny<bool>()))
.Throws(new Exception());
// Act
var result = filterController.DeleteFilter("myfilt", false);
}
}
In the end all I want to do is have it so when DeleteFilter is called for this test, an error is thrown and then I can assert what is returned from the catch block.
EDIT: have majorly updated the post by suggestion to make it easier to understand where the issue is.
Here is a slimmed down example
Given
public interface IServiceFactory {
object GetService(string args);
}
public class MyController : Controller {
IServiceFactory serviceFactory
public MyController(IServiceFactory serviceFactory) {
this.serviceFactory = serviceFactory;
}
// method under test
public ActionResult DeleteFilter(string args) {
try {
var model = serviceFactory.GetService(args);
return View(model);
} catch(Exception ex) {
return JsonActionResult(JsonReturnType.Error, ajaxMessage: "There was an error in deleting the filter.");
}
}
}
You can use moq in your test like this
[TestMethod]
public void DeleteFilter_ExceptionThrown_IsCaughtAndLoggedAndReturnsActionResultOfError() {
// Arrange
var serviceFactoryMock = new Mock<IServiceFactory>();
serviceFactoryMock
.Setup(x => x.GetService(It.IsAny<string>())
.Throws(new Exception())
.Verifiable();
var controller = new MyController(serviceFactoryMock.Object);
// Act
var result = controller.DeleteFilter("blah blah");
//Assert
serviceFactoryMock.Verify(); // verifies that the setup was invoked
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result, typeof(JsonActionResult));
//...other assertions
}
So now in the example when DeleteFilter is called, the mock service factory is invoked, an error is thrown based on the setup and you can assert what is returned from the catch block.

How can MongoDB WriteConcernResult Be mocked?

I am trying to mock a WriteConcernResult returned via an Insert();
A WriteConcernResult is returned by my provider and the Insert() is called via Add User:
private readonly IMongoProvider _repository;
public UserRepository(IMongoProvider repository)
{
_repository = repository.ForCollection("User");
}
public bool AddUser(UserModel user)
{
var result = _repository.Insert(user);
return result.DocumentsAffected > 0;
}
The MongoDB WriteConcernResult class:
public WriteConcernResult(BsonDocument response)
{
_response = Ensure.IsNotNull(response, nameof(response));
}
public long DocumentsAffected
{
get
{
BsonValue value;
return _response.TryGetValue("n", out value) ? value.ToInt64() : 0;
}
}
Because DocumentsAffected does not have a setter I am unsure how to set a value my mock will return.
{
var user = new UserModel {Name = "Test"};
_mockMongoProvider = MockRepository.GenerateMock<IMongoProvider>();
//mock writeConcernResult
var result = _repo.AddUser(user);
Assert.That(result, Is.True);
}
With a setter I would likely mock like this:
_mockMongoProvider.Stub(p => p.Insert(user))
.Return(new WriteConcernResult(
new BsonDocument()
).DocumentsAffected = 1);
Any guidance would be very helpful, cheers.
Actually you don't need to mock the WriteConcernResult class at all.
All you have to do is to initialize an instance of WriteConcernResult as the following:
var document = new BsonDocument();
document.Add("n", new BsonInt64(1));
var writeConcernResult = new WriteConcernResult(document);
Then you'll have to setup your mock repository to return this instance:
_mockMongoProvider.Stub(p => p.Insert(user))
.Return(writeConcernResult );

Preventing Autofixture from filling child collections

I'm using the latest version of Autofixture, and I'd like to prevent it from filling automatically child collections.
For example, I have a class Person that has a List property. I want all properties filled, except the list.
I tried using this customization :
public class RemoveMultiples : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations
.OfType<FilteringSpecimenBuilder>()
.Where(x => x.Specification is DictionarySpecification)
.ToList().ForEach(c => fixture.Customizations.Remove(c));
fixture.Customizations
.OfType<FilteringSpecimenBuilder>()
.Where(x => x.Specification is CollectionSpecification)
.ToList().ForEach(c => fixture.Customizations.Remove(c));
fixture.Customizations
.OfType<FilteringSpecimenBuilder>()
.Where(x => x.Specification is HashSetSpecification)
.ToList().ForEach(c => fixture.Customizations.Remove(c));
fixture.Customizations
.OfType<FilteringSpecimenBuilder>()
.Where(x => x.Specification is ListSpecification)
.ToList().ForEach(c => fixture.Customizations.Remove(c));
}
}
But it also prevents me from using .CreateMany().
edit: I can use .CreateMany(3) and it works.
Is there a setting somewhere that could let me autofill collections only when I need to?
edit2: Class person should look like this:
[Serializable]
public class Person
{
private ICollection<OtherClass> _otherClasses;
private string _something;
public virtual ICollection<OtherClass> OtherClasses
{
get { return _otherClasses; }
set { _otherClasses = value; }
}
}
Note that it's not always a Collection, but sometimes IList
Note2: I just realized that someone also removed the Customization for IEnumerable hence why the CreateMany() doesn't create anything.
Here's one way to do it.
Start by implementing a SpecimenBuilder that tells AutoFixture to skip assigning a value for collection property:
public class CollectionPropertyOmitter : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var pi = request as PropertyInfo;
if (pi != null
&& pi.PropertyType.IsGenericType
&& pi.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>))
return new OmitSpecimen();
return new NoSpecimen(request);
}
}
Then encapsulate that in a Customization:
public class DoNotFillCollectionProperties : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new CollectionPropertyOmitter());
}
}
The following tests now pass:
[Fact]
public void CreatePersonWithoutFillingCollectionProperty()
{
var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
var actual = fixture.Create<Person>();
Assert.Null(actual.OtherClasses);
}
[Fact]
public void CreateManyStillWorks()
{
var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
var actual = fixture.CreateMany<Person>();
Assert.NotEmpty(actual);
}
[Fact]
public void CreatListStillWorks()
{
var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
var actual = fixture.Create<List<Person>>();
Assert.NotEmpty(actual);
}
[Fact]
public void CreateCollectionStillWorks()
{
var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
var actual = fixture.Create<ICollection<Person>>();
Assert.NotEmpty(actual);
}

Categories

Resources