public class RefDataProvider : IRefDataProvider
{
private const string REF_DATA_COUNTRIES = "CountryData";
public IEnumerable<CountryLookupDto> GetCountries()
{
//if in cache then get cached version
if (CacheManager.GetInstance.OCache.Contains(REF_DATA_COUNTRIES))
return CacheManager.GetInstance.GetTypedItem<IEnumerable<CountryLookupDto>>(REF_DATA_COUNTRIES);
//not in cache so get from dadtavase
using (var service = new CrmServiceClient())
{
try
{
IEnumerable<CountryLookupDto> countriesDto = service.LookupCountries("*");
bool addedToCache = CacheManager.GetInstance.AddItemWithExpiration(REF_DATA_COUNTRIES, countriesDto,
12);
if (!addedToCache) throw new Exception("Cannot add ref data to cache");
}
catch (Exception ex)
{
LoggingManager.GetInstance.Log("Error", ex, LoggingManager.LogLevel.Error);
throw;
}
finally
{
service.Close();
}
}
return CacheManager.GetInstance.GetTypedItem<IEnumerable<CountryLookupDto>>(REF_DATA_COUNTRIES);
}
}
Trying to do unit test onto the method. Having problem with wcf client call.
I am trying to verify CrmServiceClient() calls in unit test. Is there any way to test wcf calls in unit test. Please advise.
[TestFixture]
public class TestRefDataProvider
{
private IReferenceDataProvider _referenceDataProvider;
[SetUp]
public void SetUp()
{
_referenceDataProvider = new ReferenceDataProvider();
}
[Test]
public void Verify_GetCountries()
{
Assert.IsNotNull(_referenceDataProvider.GetCountries());
}
}
Thanks Ilya. After Ilya explains: I came out with this:
public class ReferenceDataProvider : IReferenceDataProvider
{
private const string REF_DATA_TITLE = "TitleData";
private const string REF_DATA_COUNTRIES = "CountryData";
private readonly ICrmService _crmService;
public ReferenceDataProvider(ICrmService crmService)
{
_crmService = crmService;
}
public IEnumerable<CountryLookupDto> GetCountries()
{
//if in cache then get cached version
if (CacheManager.GetInstance.OCache.Contains(REF_DATA_COUNTRIES))
return CacheManager.GetInstance.GetTypedItem<IEnumerable<CountryLookupDto>>(REF_DATA_COUNTRIES);
try
{
IEnumerable<CountryLookupDto> countriesDto = _crmService.LookupCountries("*");
bool addedToCache = CacheManager.GetInstance.AddItemWithExpiration(REF_DATA_COUNTRIES, countriesDto,
12);
if (!addedToCache) throw new Exception("Cannot add ref data to cache");
}
catch (Exception ex)
{
LoggingManager.GetInstance.Log("Error", ex, LoggingManager.LogLevel.Error);
throw;
}
return CacheManager.GetInstance.GetTypedItem<IEnumerable<CountryLookupDto>>(REF_DATA_COUNTRIES);
}
}
My question here is I had service.Close() before. Now I can't use it. Is that safe ?
If CrmServiceClient is your WCF service so you should have an interface ICrmServiceClient.
Therefore you should not create new instance of CrmServiceClient in your code. The only thing your need is a dependency on ICrmServiceClient (e.g. via constructor)
public class RefDataProvider : IRefDataProvider
{
private readonly ICrmServiceClient crmServiceClient;
public RefDataProvider(ICrmServiceClient crmServiceClient)
{
this.crmServiceClient = crmServiceClient;
}
public IEnumerable<CountryLookupDto> GetCountries()
{
/* your code */
}
}
In this case it is possible to inject mock ok ICrmServiceClient easily.
[TestFixture]
public class TestRefDataProvider
{
private Mock<ICrmServiceClient> crmServiceClientMock;
private IReferenceDataProvider _referenceDataProvider;
[SetUp]
public void SetUp()
{
crmServiceClientMock = new Mock<ICrmServiceClient>();
crmServiceClientMock
.Setuo(/* your code */)
.Returns(/* your code */);
_referenceDataProvider = new ReferenceDataProvider(
crmServiceClientMock.Object
);
}
}
MOQ framework is used in order to mock dependencies.
Related
I am working on an application in which I am getting orders from an third party app. The application is written on windows form so I am using service stack to add routes in my application.
I have three classes. One contains endpoint
public class Service : ServiceStack.Service
{
Repository _repository;
public OrderService()
{
_repository = Repository.GetInstance();
}
[Authenticate]
public void Post(Order order)
{
if (order != null)
{
_repository.AddItem(order);
}
}
}
The second class is processing the orders and this class is a singleton class.
public sealed class Repository
{
private static object _myLock = new object();
private static Repository _mySingleton = null;
private ConcurrentQueue<Order> _queue;
public static bool orderCheck = true;
private Repository() {
_queue = new ConcurrentQueue<Order>();
}
public void AddItem(Order order)
{
_queue.Enqueue(order);
}
public static Repository GetInstance()
{
if (_mySingleton == null)
{
lock (_myLock)
{
if (_mySingleton == null)
{
_mySingleton = new Repository();
}
}
}
return _mySingleton;
}
public void CreateOrder()
{
while (orderCheck)
{
Order order = null;
_queue.TryDequeue(out order);
if (order != null)
{
try
{
// performing business logic with order
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
else
{
Thread.Sleep(10000);
}
}
}
}
The third class creates a new thread when the application is started:
new Thread(delegate ()
{
var repo = Repository.GetInstance();
repo.CreateOrder();
}).Start();
The problem is that the endpoint added the order information in the queue, but when I try to dequeue in the Repository class then it's not available on the tryDequeue method.
I put the getHashCode of ConcurrentQueue and I found the hashcode showing differently in while loop and in AddItem method.
Is it possible to pass the generic type from one class to other class generic property.
For example:
Assembly Logger
namespace Logger
{
public class GenericLoger<T>
{
T _genericLog;
LogManager _logManager;
public GenericLoger(string logName)
{
_logManager = new LogManager(logName);
//Assigning the generic type to Log.GenerciLog, this is how I am
expecting or by some other possible way?.
Log.GenerciLog = _genericLog;
}
public static Write(string description)
{
_logManager.write(description);
}
}
public static class Log
{
LogManager _logManager;
static Log()
{
_logManager = new LogManager();
}
public static Write(string description)
{
_logManager.write(description);
}
//The generic type supplied in GenericLoger need to pass here,
//like this or by some other possible way?
public static T GenerciLog { get; internal set; }
//T is unrecognized here as type is available in GenericLoger
//I want to pass here from GenericLoger
}
}
Assembly Main Caller of Logger
using Logger;
namespace DataProcessor
{
internal class SpecialLogger
{
private static Lazy<GenericLog<SpecialLogger>> _passed;
public static GenericLog<SpecialLogger> Passed
{
get
{
if (_passed == null)
{
_passed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Passed"), true);
}
return _passed.Value;
}
}
private static Lazy<GenericLog<SpecialLogger>> _failed;
public static GenericLog<SpecialLogger> Failed
{
get
{
if (_failed == null)
{
_failed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Failed"), true);
}
return _failed.Value;
}
}
}
internal class Processor
{
public void ProcessRate()
{
var trans = dataManager.GetData();
//Will write the log in "Log.txt" file
Log.write(trans.Count + " transaction found");
foreach (var item in trans)
{
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' property I want to access like this
Log.GenerciLog.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' property I want to access like this
Log.GenerciLog.Failed.Write(item);
}
}
}
}
}
NOTE: In .NET you don't have a way for automatic type inference for use case like yours, also there is no automatic type substitution.
Not sure if this is what you are looking for
Your method definition should look like this
public static T GenerciLog<T> { get; internal set; }
and this is how to call it
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Failed.Write(item);
}
This is a very simple log class. There is a lot more you could do with this sort of thing. Its all provided by log4net which I'd recommend using rather than trying to write your own logger. But the below is a start of how I'd implement a simple logger. It allows you to log to several different things at once. I appreciate the below doesn't answer exactly what you want but its an indication of how to start and you can adapt it to suit your needs.
public static class Logger
{
private static List<ILogger> _loggers = new List<ILogger>();
public static void Log(string message)
{
foreach (var logger in _loggers)
logger.Write(message);
}
public static void AddLogger(ILogger logger)
{
_loggers.Add(logger);
}
}
public interface ILogger
{
void Write(string message);
}
public class SpecialLogger : ILogger
{
public void Write(string message)
{
//special log code here eg
Console.WriteLine(message);
}
}
then somewhere do this
Logger.AddLogger(new SpecialLogger());
Logger.Log("A log message");
I have the following code
[Quartz.DisallowConcurrentExecutionAttribute()]
public class SearchIndexJob : IJob
{
private readonly ILog _Log = null;
private SearchManager _SearchManager;
public SearchIndexJob()
{
_Log = LogManager.GetLogger(GetType());
}
#region IJob Members
public void Execute(IJobExecutionContext context)
{
var container = new StructureMap.Container();
IServiceConfigurationProvider services = new StructureMapConfiguration(container);
var locator = new EPiServer.ServiceLocation.StructureMapServiceLocator(container);
var context2 = new EPiServer.ServiceLocation.ServiceConfigurationContext(HostType.WebApplication, services);
new Mediachase.Commerce.Initialization.CommerceInitialization().ConfigureContainer(context2);
container.Configure(ce =>
{
ce.For<IMarketService>().Use<MarketServiceDatabase>();
ce.For<IMarket>().Use<MarketImpl>();
ce.For<ICurrentMarket>().Singleton().Use<Mediachase.Commerce.Markets.CurrentMarketImpl>();
ce.For<ISynchronizedObjectInstanceCache>().Singleton().Use<EPiServer.Events.RemoteCacheSynchronization>();
ce.For<IObjectInstanceCache>().Use<HttpRuntimeCache>();
//ce.For<ITypeScannerLookup>().Use<FakeTypeScannerLookup>();
ce.For<IWarehouseRepository>().Singleton().Use<Mediachase.Commerce.Inventory.Database.WarehouseRepositoryDatabase>();
ce.For<IChangeNotificationQueueFactory>().Singleton().Use<CommerceChangeQueueFactory>();
ce.For<IPriceService>().Singleton().Use<PriceServiceDatabase>();
ce.For<IPriceDetailService>().Use<PriceDetailDatabase>();
ce.For<IWarehouseInventoryService>().Singleton().Use<WarehouseInventoryProxy>();
ce.For<IInventoryService>().Singleton().Use<InventoryServiceProvider>();
ce.For<IApplicationContext>().Use<FakeAppContext>();
ce.For<CatalogConfiguration>().Use(CatalogConfiguration.Instance);
ce.For<IRequiredMetaFieldCollection>().Singleton().Use<DefaultRequiredMetaFields>();
ce.For<MetaDataContext>().Singleton().Use(() => CatalogContext.MetaDataContext);
//ce.For<EventContext>().HybridHttpOrThreadLocalScoped().Use(eventContext);
ce.For<FrameworkContext>().Use(() => FrameworkContext.Current);
//ce.For<SqlContext>().Use(() => new SqlContext(BusinessFoundationConfigurationSection.Instance.Connection.Database));
ce.For<IChangeNotificationManager>().Singleton().Use<ChangeNotificationManager>();
////ce.For<Mediachase.Commerce.Catalog.ICatalogSystem>().Singleton().Use(() => Mediachase.Commerce.Catalog.CatalogContext.Current);
ce.For<IEventRegistry>().Use<EPiServer.Events.Clients.EventRegistry>();
ce.For<IEventBroker>().Use<FakeEventBroker>();
ce.For<Mediachase.Search.IndexBuilder>().Use<FakeIndexer>();
});
EPiServer.ServiceLocation.ServiceLocator.SetLocator(locator);
string applicationName = context.JobDetail.Description;
if (String.IsNullOrEmpty(applicationName) || applicationName == "all") // index all applications
{
AppDto dto = AppContext.Current.GetApplicationDto();
foreach (AppDto.ApplicationRow row in dto.Application)
{
IndexApplication(row.Name);
}
}
else
{
IndexApplication(applicationName);
}
}
#endregion
void IndexApplication(string applicationName)
{
_Log.Info(String.Format("Creating Search Manager for \"{0}\" Application.", applicationName));
_SearchManager = new SearchManager(applicationName);
_Log.Info("Created Search Manager.");
try
{
_SearchManager.SearchIndexMessage += new SearchIndexHandler(_SearchManager_SearchIndexMessage);
_SearchManager.BuildIndex(true);
}
catch (Exception ex)
{
_Log.Error("Search Manager Failed.", ex);
}
}
void _SearchManager_SearchIndexMessage(object source, SearchIndexEventArgs args)
{
_Log.Info(String.Format("Percent Complete: {0}%, {1}", Convert.ToInt32(args.CompletedPercentage), args.Message));
}
}
public class FakeEventBroker : IEventBroker
{
public bool Enabled { get; set; }
public System.Threading.Tasks.Task RaiseEventAsync(Guid eventId, Object parameter)
{
return null;
}
public event EventHandler<EventReceivedEventArgs> EventReceived;
public event EventHandler<EventMissedEventArgs> EventMissed;
}
public class FakeAppContext : IApplicationContext
{
public bool HasContentModelTypes { get; set; }
public bool DisableVersionSync { get; set; }
}
public class FakeIndexer : Mediachase.Search.IndexBuilder
{
public FakeIndexer() : base("","","")
{
}
}
and I get this error
"No default Instance is registered and cannot be automatically determined for type 'EPiServer.Framework.Cache.IRequestCache"
in this line " _SearchManager.BuildIndex(true);"
Any ideas?
It is hard to tell but I assume you need to register the IRequestCache in your container
I.e.
container.Configure(ce =>
{
ce.For<IMarketService>().Use<MarketServiceDatabase>();
ce.For<IMarket>().Use<MarketImpl>();
ce.For<IRequestCache>().Use<NoRequestCache>(); // or whatever implementation you need
...
}
Schedule Job is trying to Intialize Commerce, Most probably you will require to fix more then IRequestCache including DBContext, See an integration sample here. GIT Integration Sample
I have a class that calls out to an internet service to get some data:
public class MarketingService
{
private IDataProvider _provider;
public MarketingService(IDataProvider provider)
{
_provider = provider;
}
public string GetData(int id)
{
return _provider.Get(id);
}
}
Currently I have two providers: HttpDataProvider and FileDataProvider. Normally I will wire up to the HttpDataProvider but if the external web service fails, I'd like to change the system to bind to the FileDataProvider . Something like:
public string GetData(int id)
{
string result = "";
try
{
result = GetData(id); // call to HttpDataProvider
}
catch (Exception)
{
// change the Windsor binding so that all future calls go automatically to the
// FileDataProvier
// And while I'm at it, retry against the FileDataProvider
}
return result;
}
So when this has been executed all future instances of MarketingService will automatically be wired up to the FileDataProvider. How to change a Windsor binding on the fly?
One solution would be using selector
public class ForcedImplementationSelector<TService> : IHandlerSelector
{
private static Dictionary<Type, Type> _forcedImplementation = new Dictionary<Type, Type>();
public static void ForceTo<T>() where T: TService
{
_forcedImplementation[typeof(TService)] = typeof(T);
}
public static void ClearForce()
{
_forcedImplementation[typeof(TService)] = null;
}
public bool HasOpinionAbout(string key, Type service)
{
return service == typeof (TService);
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
var tService = typeof(TService);
if (_forcedImplementation.ContainsKey(tService) && _forcedImplementation[tService] != null)
{
return handlers.FirstOrDefault(handler => handler.ComponentModel.Implementation == _forcedImplementation[tService]);
}
// return default
return handlers[0];
}
}
Test and usage
[TestFixture]
public class Test
{
[Test]
public void ForceImplementation()
{
var container = new WindsorContainer();
container.Register(Component.For<IFoo>().ImplementedBy<Foo>());
container.Register(Component.For<IFoo>().ImplementedBy<Bar>());
container.Kernel.AddHandlerSelector(new ForcedImplementationSelector<IFoo>());
var i = container.Resolve<IFoo>();
Assert.AreEqual(typeof(Foo), i.GetType());
ForcedImplementationSelector<IFoo>.ForceTo<Bar>();
i = container.Resolve<IFoo>();
Assert.AreEqual(typeof(Bar), i.GetType());
ForcedImplementationSelector<IFoo>.ClearForce();
i = container.Resolve<IFoo>();
Assert.AreEqual(typeof(Foo), i.GetType());
}
}
Alternatively you could create a proxy:
public class AutoSelectingDataProvider : IDataProvider
{
public AutoSelectingDataPovider(HttpDataProvider httpDataProvider, FallBackDataProvider fallBackProvider)
{
_httpDataProvider = httpDataProvider;
_fallBackDataProvider = fallBackDataProvider;
}
public string GetData(int id)
{
try
{
return _httpDataProvider.GetData(id);
}
catch (Exception)
{
return _fallBackDataProvider.GetData(id);
}
return result;
}
}
container.Register(
Component.For<HttpDataProvider>(),
Component.For<FallBackDataProvider>(),
Component.For<IDataProvider>().ImplementedBy<FallBackDataProvider>());
This will always first try to get data from the HttpDataProvider if not succesfull use the fallback. If you want you can introduce state and after a failure always use the fallback. This way you can keep using the IDataProvider in your application without needing to obtain a new one from the container.
before I begin with my question I want to point out that I am aware that there are tons of similar questions on stack overflow. Unfortunately none of these questions helped me finding a good solution in my concrete scenario.
The Problem:
I want to write a unit test for a static factory method which contains logic. I am looking for a way to unit test this method even if it is static. If that is not possible maybe someone can point out a better design for my class under test. I also considered using IoC but couldn't see the advantage considering unit-testing.
The Code:
public class Db
{
private XmlMapping mapping;
public static Db<T> Create()
{
var mapping = XmlMapping.Create(typeOf(T).Name);
return new Db(mapping);
}
private Db(XmlMapping mapping)
{
this.mapping = mapping;
}
}
public class XmlMapping //class under test
{
public static XmlMapping Create(string filename) //method under test
{
try
{
ValidateFilename(filename);
//deserialize xml to object of type XmlMapping
var result = Deserialize(filename);
if (result.IsInValid())
throw Exception()
return result;
}
catch (Exception)
{
throw new DbException();
}
}
}
The method Create which I want to unit test is within the class XmlMapping. This method serializes a xml file and generates an object of type XmlMapping. I tried to write a stub for the serialization part. But didn't want to call my Database Factory with a Mapping class in the constructor (constructor injection).
Edit:
My database factory is generic. The generic type is used to figure out which xml file should be louded i.e.: typeOf(T) = Customer --> XmlMapping-File = Customer.xml
The Solution (Thx to Jeff!):
public class XmlMapping : IMapping //class under test
{
internal static Func<Type, IMapping> DeserializeHandler { get; set; }
static XmlMapping()
{
DeserializeHandler = DeserializeMappingFor;
}
public static IMapping Create(Type type)
{
try
{
var mapping = DeserializeHandler(type);
if (!mapping.IsValid())
throw new InvalidMappingException();
return mapping;
}
catch (Exception ex)
{
throw new DataException("Failed to load mapping configuration from xml file.", ex);
}
}
internal XmlMapping(IMapping mapping)
{
this.Query = mapping.Query;
this.Table = mapping.Table;
this.Entity = mapping.Entity;
this.PropertyFieldCollection = mapping.PropertyFieldCollection;
}
private XmlMapping() { }
}
[TestClass]
public class MappingTests //testing class
{
[TestMethod]
public void Create_ValidDeserialization_ReturnsObjectInstance()
{
XmlMapping.DeserializeHandler = MakeFakeHandlerFor(MakeMappingStub());
var result = XmlMapping.Create(typeof(ActivityDto));
Assert.IsInstanceOfType(result, typeof(XmlMapping));
}
}
I would use a fake action handler to assist in verifying the content of the call to deserialize. Let's add a Func delegate property and default that to your serialize method. Your XmlMapping class and test would like something like:
public class XmlMapping //class under test
{
static XmlMapping()
{
// Default the handler to the normal call to Deserialize
DeserializeHandler = Deserialize;
}
public static XmlMapping Create(string filename) //method under test
{
//deserialize xml to object of type XmlMapping
//preudocode:
var result = DeserializeHandler(string.Format("{0}.xml",filename));
//...
return result;
}
// Abstract indirection function to allow you to swap out Deserialize implementations
internal static Func<string, XmlMapping> DeserializeHandler { get; set; }
private static XmlMapping Deserialize(string fileName)
{
return new XmlMapping();
}
}
public class CreateTests {
public void CallingDeserializeProperly()
{
// Arrange
var called = false;
Func<string, XmlMapping> fakeHandler = (string f) =>
{
called = true; // do your test of the input and put your result here
return new XmlMapping();
};
// Act
XmlMapping.DeserializeHandler = fakeHandler;
var m = XmlMapping.Create("test");
// Assert
Assert.IsTrue(called);
}
}