I have code like the following in many files. The code is the same in every file.
#if SOMETHING
using namespace1;
#else
using namespace2;
#endif
However I don't want to have to maintain these same five lines in many files.
Ideally I would like to do something like this in a separate file:
#if SOMETHING
var namespace = namespace1;
#else
var namespace = namespace2;
#endif
And then in all the other files:
using namespace
How can I achieve something like this?
I would avoid having the same code in different namespaces twice to start with.
Just generate the code once, but then wherever you create an instance of the web service, specify the URL you want to connect to. (You probably want to centralize that code, mind you.)
Look at the properties in the web service - I'm sure one of them will be the base URL. Just because it defaults to one particular URL (ideally something invalid, so that you never end up making accidental calls to the wrong environment due to not setting it) doesn't mean you can't change it programmatically at execution time.
You're going about it the wrong way. Don't have 2 references, just have one to the test service and then in the production build of your application, change the URL in the app/web config to point to the production URL.
Related
I need to process an input xml using one of two namespaces depending on whether a value in the xml has a test or live flag. The namespaces contain classes that are virtually identical. So far I have not been able to do this without writing 2 entire classes that are identical except for the namespace in use.
I have seen some solutions to this in other programming languages using interfaces that return different types. I don't see how this is possible in C#.
using wsdlns = MyCompany.MyLibrary.DevelopmentWSDL;
.
.
.
public void ProcessXml(XmlToProcess xml)
{
if(xml.live == 1)
{
wsdlns = MyCompany.MyLibrary.ProductionWSDL;
}
wsdlns.ProcessingClass processingObject = new wsdlns.ProcessingClass();
.
.
.
}
The above code comes back with a "MyCompany.MyLibrary.ProductionWSDL is a namespace but is used like a variable error".
It's impossible to change the namespace at run-time, and there is no dynamic solution to it, and I don't believe there will ever be in the future.
You can handle this at MyLibrary level.
instead of having two different namespaces for development and production, you will need to combine them into one namespace. and from the code, you can use regular if statement to switch between them.
Or Better yet, use preprocessor directives which are design are designed for this kind of purpose. It will help the compile to know which part you need to be compiled on Debug mode, and which one to be on Release mode.
for instance, in your case #if and #define preprocessors can be used. For instance, for the development class you do this :
#define DEVELOPMENT
using System;
//... rest of the class
you do also the same for the production.
Then, you can use #if
#if (DEBUG && DEVELOPMENT)
//Some code here will only run on Debug mode only.
#else
//Run the production version
#endif
Like most web applications mine has static resources that must be part of the deployment or the user receives a 404 response from the server. My thought was to use unit testing to validate two things 1. the resource exists, and 2. the content was not modified. I have tried the following code but it expects (I think) that the files exist in the unit test project.
Solution structure:
WebApplicationProject
- ...
- public
- file.*
- otherfile.*
- web.config
WebApplicationProject.Tests
- AssetTests.cs
Am I going about this all wrong, should this not be part of a unit test and some other gait on the CI build process (Azure DevOps), or am I missing something super obvious? I'm likely asking the wrong questions and going about this the wrong way, because I know I'm not the first person to want to do something like this.
I've read other posts around testing with files, but they all are using test files to drive data for input in some method that consumes the file, or some process that generates a file for comparison. I don't want to do either of these things.
I have also played with the settings making the file an embedded resource, and to always deploy with the project, but the unit test project still cannot access the file the way I'm going about this.
[TestClass]
public class AssetTests
{
[TestMethod]
[DeploymentItem(#".\files\file.*")]
public void AwardLetters()
{
string path = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "file.*");// gets the working path for the testing dll, no files exist here.
Assert.IsTrue(File.Exists("file.*"), "FAIL: file {0} not found", "file.*");// nothing I have tried has access to the projects static resources
}
}
All results end in a file not found exception so far.
I did try to load the reference manually using:
Assembly a = Assembly.LoadFrom("WebApplicationProject");// also used WebApplicationProject.dll
This fails to find the reference. Yes, the reference property copy local is set to true.
I am open to all suggestions, but if you suggest that I have two copies of the files, please fully explain why this is desirable.
Alright here's my MVP. I'll leave this open for a while though in hopes someone has a better solution, it cant be this difficult to access the resources like this, I feel like there should be a way to access the applications directory without having to embed the file in the assembly just to pass it to a test method.
[TestMethod]
public void FileExists()
{
Assembly a = Assembly.LoadFrom(#"..\..\..\WebApplicationProject\bin\WebApplicationProject.dll");
string t = string.Join("", a.GetManifestResourceNames());
Assert.IsTrue(t.Contains("file.*"));
}
Now that I have the file I can also create a test to test the content of the file to validate it's contents.
I still think this is duck tape and it's not elegant at all. So please share your answers and critiques of my solution.
In Visual Studio IDE, I can create a unit test file with a unit test class for the code in a source file, by right clicking inside the code to be tested and selecting the option to create unit test.
The testing code and the code to be tested are not only in the same file, but also not in the same namespace.
Is it possible to write the code to be tested and the testing code in the same source file?
If yes, how? Should I put them in the same or different namespaces?
Can you give some examples?
Thanks.
It is possible, but that also means that you deploy your tests with your code, as well as any mocks, dummy data, etc. All of this is unnecessary and may confuse anyone trying to use the library.
However, to answer the question, just use different namespace blocks to separate the test classes in a separate namespace.
namespace MyCompany.MyLibrary
{
// classes
}
namespace MyCompany.MyLibrary.Test
{
// tests, mocks, etc.
}
Yes, there is no restrictions where "code under test" is coming from.
While it is somewhat strange you can have just UnitTest project and put code you trying next to your tests. If you want - even in the same files using same or different namespaces of your choice (C# is not Java and there is no connection bewteen file name/location and namespace)
Yes, but
If you put them in the same code base as the system under test, then you will be unable to deploy the system without also deploying the tests. Do you want the tests sitting on your production servers?
Also, the same app.config (or web.config, depending on your solution) will apply to both your tests and the system under test. That means you can't set up alternate configurations for things like AutoFac, which normally is handy for unit/isolation testing.
I have an internal API that I would like others to reference in their projects as a compiled DLL. When it's a standalone project that's referenced, I use conditional compilation (#if statements) to switch behavior of a key web service class depending on compilation symbols. The problem is, once an assembly is generated, it appears that it's locked into whatever the compilation symbols were when it was originally compiled - for instance, if this assembly is compiled with DEBUG and is referenced by another project, even if the other project is built as RELEASE, the assembly still acts as if it was in DEBUG as it doesn't need recompilation. That makes sense, just giving some background.
Now I'm trying to work around that so I can switch the assembly's behavior by some other means, such as scanning the app/web config file for a switch. The problem is, some of the assembly's code I was switching between are attributes on methods, for example:
#if PRODUCTION
[SoapDocumentMethodAttribute("https://prodServer/Service_Test", RequestNamespace = "https://prodServer", ResponseNamespace = "https://prodServer")]
#else
[SoapDocumentMethodAttribute("https://devServer/Service_Test", RequestNamespace = "https://devServer", ResponseNamespace = "https://devServer")]
#endif
public string Service_Test()
{
// test service
}
Though there might be some syntactical sugar that allows me to flip between two attributes of the same type in another fashion, I don't know it. Any ideas?
The alternative method would be to reference the entire project instead of the assembly, but I'd rather stick with just referencing the compiled DLL if I can. I'm also completely open to a whole new approach to solve the problem if that's what it takes.
You don't need to do this. Those URLs are not "real" URLs - they do not represent locations on the Internet. They are only used to make names unique.
You should use the same namespace name for dev as for production.
The thing is, the #if statements are ran against only during compilation.. Once you have a compiled assembly - it's going to stick with what it had.. The rest of the code is stripped out from the assembly :)
If you want the URLs to be different for your test/production, you should create a new attribute, that derives from SoapDocumentMethodAttribute, and sets these values depending on your AppSetting values :)
Well, ok - first, OBVIOUSLY a conditional COMPILE stays in place after the compile. How the heck did you get the idea it was otherwise? It is a conditional COMPILE.
Attributes yo ucan fix with reflection - you can "override" reflection to return your own information there. It iws tricky, but it is possible (same way you can "inject" properties into reflection code). Not sure I would like that to happen, though. Basically... you should get something like a server URL not from reflection but from the config file. Wrong approach, I would say.
I have a web service class that the rest of the framework depends on to grab its data, but the web service class needs to have different method attributes depending on what environment it's in. For instance...
[SoapDocumentMethodAttribute("https://example",...)]
public string Test()
{
//doSomething
}
See that "https://example"? That needs to change depending on the environment. AFAIK you can't make that string dynamic for runtime, it has to be compiled that way. So I'm trying to get it so that I have multiple CS files for this web service that have the different attribute URLs hardcoded in them, and MSBuild swaps them on precompile. So I'd have a base "Service.cs" for testing, "Service.cs.production" for the production environment, and so on.
Is this the best way to do this, or am I missing something where I can have one CS that handles the environment on its own?
To preserve having the same class name and IntelliSense not thinking things are ambiguous, I'm mucking up the file extensions ("Service.cs" versus "Service.cs.production"). Is that the only way to do it?
Considering all the above is OK, and I'm compiling against a "Production" configuration, can it compile Service.cs.production instead of Service.cs and everything goes hunky-dorey?
Thanks!
Could you use conditional comments?
#if TESTING
[SoapDocumentMethodAttribute(something)]
#else
[SoapDocumentMethodAttribute(someotherthing)]
#endif
For your test configuration you would define the constant:
<DefineConstants>TESTING</DefineConstants>
In conjunction with Defining constants, and using #if directives,
You can also write a custom build task -> Target BeforeBuild, then using the Engine.GlobalEngine.GetLoadedProject("projpath") in to Project object.
Now you can manipulate the properties on the Project object however you want for different environments.
Consider adding Platforms in the configuration, for different environments if you want to.
This may not be the answer you are looking for, but something to consider when you want to fork build based on project environments.