C# - MEF - Importing from a Portable Class Library - c#

I can't seem to be able to load a class exported from a PCL DLL in a regular Windows DLL.
I am using the Nuget Package: http://www.nuget.org/packages/Microsoft.Composition/ (Microsoft Composition (MEF 2) 1.0.27)
Passing Code (inside a regular DLL):
using System.ComponentModel.Composition;
namespace Normal
{
[Export]
public class TestExport
{
}
}
Failing Code (inside a PCL DLL):
using System.Composition;
namespace PCL
{
[Export]
public class TestExport
{
}
}
Unit Test (Regular Unit Test Project):
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PCL;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace UnitTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(PCL.TestExport).Assembly));
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Normal.TestExport).Assembly));
var container = new CompositionContainer(catalog, CompositionOptions.DisableSilentRejection);
CompositionBatch batch = new CompositionBatch();
batch.AddExportedValue(container);
container.ComposeParts(batch);
//Passes
PCL.TestExport constructed = new PCL.TestExport();
Normal.TestExport constructed2 = new Normal.TestExport();
//Passes
Normal.TestExport passes = container.GetExportedValue<Normal.TestExport>();
//Fails
PCL.TestExport e = container.GetExportedValue<PCL.TestExport>();
}
}
}

Your regular DLL and unit test project are using System.ComponentModel.Composition, which is "MEF 1". MEF 1 doesn't know anything about the System.Composition attributes (MEF 2).
If you can use MEF 2 for all your projects, it should work.

Related

Visual Studio 2022 not running XUnit tests

I've created a EntityFramework ASP.NET solution and i'm trying to create a XUnit test project to test my differents classes i've created.
I've created a TestClass for my Activity Class :
using LADS_Model;
using LADS_WebUI.Controllers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using Xunit;
using Assert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
namespace LADS_XUnit
{
public class UnitTest_Activity
{
[TestClass]
public class ActivityController
{
private List<Activity> GetTestActivities()
{
var testActivities = new List<Activity>();
testActivities.Add(new Activity { Id = 1, Name = "Chaussure" });
testActivities.Add(new Activity { Id = 2, Name = "Crevettes" });
testActivities.Add(new Activity { Id = 3, Name = "Sandwich" });
return testActivities;
}
[TestMethod]
public void GetAllActivities_ShouldReturnAllActivities()
{
var testActivities = GetTestActivities();
var controller = new ActivityController();
var result = controller.GetTestActivities();
Assert.Equals(testActivities.Count, result.Count);
}
}
}
}
The problem is that when I launch my testClass, I do have the Test showing up in the test Explorer but VS tells me that the test did not execute and I have no idea why because it's not showing any errors or any messages to explain why it didnt execute
Output of Tests :
You're using the wrong method attributes for xUnit, so the xUnit Runner won't discover your tests:
You're using [TestClass] and [TestMethod], but xUnit uses [Fact] (and [Theory], and others) only on methods, and doesn't use any attributes on test class` types.
xUnit's website has a table that matches and compares NUnit's, xUnit's, and MSTest's attributes.
So remove all [TestClass] attributes and change all [TestMethod] attributes to [Fact].
I see you have this:
using Assert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
...so I assume you're porting existing MSTest code to xUnit, in which case rather than changing the attributes in your code-base, you could alias MSTest's attributes to xUnit:
using TestClassAttribute = SomeDummyAttribute;
using TestMethodAttribute = Xunit.FactAttribute;
internal sealed class SomeDummyAttribute : Attribute {}
If you're using C# 10.0 or later you can use global using which will be shared by all source-files in the same project.
Also, consider using Shouldly or Fluent Assertions instead of the Assert/Asserts classes.

MEF - Export Module not loaded

Following MEF Export will not be loaded by ComposeParts(this).
using MyLib;
using System.Composition;
namespace Test
{
[Export(typeof(IExtension))]
public class Test : IExtension
{
}
}
This happens when you auto-install MEF to dotnetcore using Visual Studio Alt+Enter menu. The correct namespace is System.ComponentModel.Composition. Due to quite similarly named namespace this may be overseen.
using MyLib;
using System.ComponentModel.Composition; // <--
namespace Test
{
[Export(typeof(IExtension))]
public class Test : IExtension
{
}
}

Unity, Moq, and NUnit - Controller Constructor with Parameters Not Recognized in Tests

I am very new to unit testing, so I apologize if this is not a very good question.
I have a main web project, and an accompanying NUnit tests library. I am using Unity to inject interfaces into my controller within the main project. For example:
public class EquipmentController : Controller
{
private readonly ILocationRepository locationContext = null;
private readonly IRepository<EquipmentCategory> categoryContext = null;
private readonly IEquipmentRepository equipmentContext = null;
private readonly IRecordRepository recordContext = null;
public EquipmentController(ILocationRepository locationRepo, IRepository<EquipmentCategory> categoryRepo, IEquipmentRepository equipmentRepo, IRecordRepository recordRepo)
{
this.locationContext = locationRepo;
this.categoryContext = categoryRepo;
this.equipmentContext = equipmentRepo;
this.recordContext = recordRepo;
}
The web application itself actually works as expected. However, I am encountering issues while trying to write test cases. For example, in test library, I have the following:
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity.Mvc;
using Microsoft.Practices.Unity.ObjectBuilder;
using Microsoft.Practices.Unity.StaticFactory;
using Moq;
using ITEquipmentDatabase;
using ITEquipmentDatabase.Models;
using ITEquipmentDatabase.Controllers;
namespace ITEquipmentDatabase.Tests
{
[TestFixture]
public class EquipmentController
{
[Test]
public void TestMethod()
{
var equipRepo = new Mock<IEquipmentRepository>();
var categoryRepo = new Mock<IRepository<EquipmentCategory>>();
var locationRepo = new Mock<ILocationRepository>();
var recordRepo = new Mock<IRecordRepository>();
EquipmentController controller = new EquipmentController(locationRepo.Object, categoryRepo.Object, equipRepo.Object, recordRepo.Object);
}
}
}
However, I am receiving the following error:
Error 1 'ITEquipmentDatabase.Tests.EquipmentController' does not contain a constructor that takes 4 arguments C:\Users\Khandokar\Documents\Visual Studio 2013\Projects\IT Equipment Log\ITEquipmentDatabase.Tests\EquipmentController.cs 27 46 ITEquipmentDatabase.Tests
I have Unity referenced in my tests project and even added Bootstrapper.cs (not sure if it was necessary, but I was trying to resolve the above issue). I am quite sure I am doing something very wrong, but I am just starting to venture into unit testing and am having a bit of a difficult time.
Thanks for any advice.
Your test class is named EquipmentController and so is your class under test.
Rename your test class to EquipmentControllerTests or some such.
(The error message was the clue; note that it refers to Tests.EquipmentController).

TestContext is null when running test from a Windows Form

I have an issue related to running CodedUITests from a Windows Form. (it works in the CodedUITestProject with Test-Explorer).
This is my CodedUITest's structure :
[CodedUITest]
public class DBTest
{
#region Static Fields
public static CSVReader csvReader;
#endregion
#region Fields
public string logFileName;
public string timer = String.Empty;
public TestRead testRead;
public UploadResults uploadResults;
private DateTime testStart;
#endregion
[ClassInitialize]
public static void MyTestInitialize(TestContext test)
{
csvReader = new CSVReader();
csvReader.LoadTestValues("steam.csv");
}
[TestInitialize]
public void testInit()
{
testStart = DateTime.Now;
}
[TestMethod(), TestCategory("Reflection"), TestCategory("DataDriven"), DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", #"|DataDirectory|\CSV's\steam.csv", "steam#csv", DataAccessMethod.Sequential), DeploymentItem(#"..\..\CSV's\steam.csv")]
public void steamAccess()
{
testRead = new TestRead();
SteamMap a = new SteamMap();
testRead.Read(a, TestContext);
}
[TestCleanup]
public void TestCleanup()
{
uploadResults = new UploadResults();
//timer for each test ( in seconds )
double diffSecs = (DateTime.Now - testStart).TotalSeconds;
uploadResults.TestUpload(testRead.TestResults, csvReader.DataTable, diffSecs,TestContext);
}
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
private TestContext testContextInstance;
}
This runs perfectly from VS's Test Explorer, testContextInitialize variable gets initialized.
In the same Solution I've added a second project, a simple Windows Form application, added a reference to my DLL ( from References) which runs the following code :
Playback.Initialize();
DBTest a = new DBTest();
a.steamAccess();
Playback.Cleanup();
NullReferenceException occurs, my testContex is null when I run my test from outside it's assembly.
I need some help in this matter, Thanks
Edit 1:
Test Class :
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Windows.Input;
using System.Windows.Forms;
using System.Drawing;
using Microsoft.VisualStudio.TestTools.UITesting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestTools.UITest.Extension;
using Keyboard = Microsoft.VisualStudio.TestTools.UITesting.Keyboard;
using System.Linq;
using System.Reflection;
using SimarpiDB.GLobal;
using SimarpiDB.UITestMaps.SteamMapClasses;
using SimarpiDB.Global;
using System.Data;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("TestLauncher")]
namespace SimarpiDB
{
[CodedUITest]
public class.....
Edit 2:
Temporary workaround until I find the cause of this error :
From my Windows Form I launch a MSTest with few required parameters and most of the what-methods-to-run logic will come from my database. I already did this few months ago but I scraped it because it's an additional performance overhead to use a tool such as MsTest within a launcher such as mine.
For anyone interested, there's a file located within VS's installation directory, it's called VsDevCmd.bat, I load this .bat within a hidden-in-background cmd with few additional commands ( mstest, testcontainer, test). This works but as I said I have no other plausible ideas.
There may also be a lack of referenced libraries within my Form ? Maybe something, a .dll that initialized the testenvironment and the testContext variable.
I wrote this because there may be others seeking the same result.
To clarify on my comment: internal is default in C#, so declaring something as abstract is like declaring it as "internal abstract".
For InternalsVisibleTo, you must make the library project visible to the test project, not the other way around:
[assembly:InternalsVisibleTo("MyTestProject")]

The name 'Installers' does not exist in the current context

I'm a total noob in developing windows services and I found a tutorial about implementing a standard windows service. This is the code that I found:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace ReviewsSvc
{
[RunInstaller(true)]
public class ReviewsSvcInstaller
{
private ServiceProcessInstaller processInstaller;
private ServiceInstaller serviceInstaller;
public ReviewsSvcInstaller()
{
processInstaller = new ServiceProcessInstaller();
serviceInstaller = new ServiceInstaller();
processInstaller.Account = ServiceAccount.LocalSystem;
serviceInstaller.StartType = ServiceStartMode.Manual;
serviceInstaller.ServiceName = "Reviews Updater";
Installers.Add(serviceInstaller);
Installers.Add(processInstaller);
}
}
}
I've added the necessary references but I still get an error about 'Installers' not found. What am I missing?
You forgot to specify the base class
namespace ReviewsSvc
{
[RunInstaller(true)]
public class ReviewsSvcInstaller : Installer
{
....
Make sure the class ReviewsSvcInstaller in the main executable (EXE). The installer look for this class in the main entry assembly. I hope it helps.

Categories

Resources