Get all classes and interfaces that are used in another class with Roslyn? - roslyn

the question is this: I have some source file:
namespace TestSln
{
public class AAA
{
private DDD x;
private void func(CCC z)
{
BBB b = new BBB();
b.z();
}
}
}
The output I'm looking for is this:
The class AAA uses: "DDD, CCC, BBB"
How can I achieve this with Roslyn?
P.S. I want to be able to read the entire solution, and search in all the projects for classes that are referenced in this source file.

Create your own SyntaxWalker, and call GetSymbol() on your SemanticModel for every node in Visit(). You can simply add each symbol to a Set<ISymbol> to collect a full list.

Related

C++ google test, mocks not called on inherited classes

As said in the title, I try to test my code using google test, but I get some issue on inheritance of mocks.
I will further present the structure of my code:
file1.hpp
struct A: virtual public testing::Test
{
//function with MocksA
};
file2.hpp
struct B: virtual public testing::Test
{
//function with MockB
};
file3.hpp
include file1 & file2
class C: public B, public A
{
//call MockB -> fails here
};
If I only use the inheritance on "public B" or would put "public B" on 2nd position, the code works. However, I need both A & B to be tested in my class C and would get the same error for A (or B, depending the position).
How can I include both files and use their mocks?
P.S: both A&B have different names for MOCKS and would not influence one another.
P.S 2: If situation is as above, I get:
unknown file: Failure
C++ exception with description "
The mock function has no default action set, and its return type has no default value set." thrown in the test body.
Actual function call count doesn't match EXPECT_CALL(...,.. )...
Expected: to be called once
Actual: never called - unsatisfied and active
The solution was to add EXPECT_CALLS in the 3rd file, not using the ones from file1 & file2

Methods to be only available in Unit test

I'm looking for a way to make methods only available in Unit test scripts.
public class MyClass
{
public Data MyData { get; }
internal MyClass()
{
// Complex code setting MyData
}
#if UNITY_MACROS
public MyClass(MyData data)
{
MyData = data;
}
#endif
}
The need is that the public constructor would only be available in the Unit Test scripts and assembly.
I tried to look into Define constraints in the Test assembly but I am probably not using right since I don't see any difference.
What you need is to use the InternalsVisibleTo attribute (MS docs). You can add the following line either in your class source file, or in a separate AssemblyInfo.cs which you can create in the same folder as your asmdef file:
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyUnitTestAssembly")]
In that case you can leave MyClass(MyData data) internal.

Regexp to find public members in Java source files

In a language built on top of Java (so I cannot use regular parsers) I want to parse several sourc code files an extract the following information:
name and extends/implements part of public (inner) classes
public method declarations
So for a given file
public class A extends B {
private int foo
public int getFoo() {
...
}
private class Inner1 {
}
public class Inner2 {
}
}
I would like to get with a single or several Regexps:
public class A extends B
public int getFoo()
public class Inner2
Let me know if this isn't quite complex enough, but it will basically look for "public" followed by a space, then anything that isn't an opening curly brace:
public\s[^{]+
Output is below:
You'll want lines that start with any amount of whitespace, followed by public, followed by some whitespace, followed by a word character:
^\s*public\s+\w

How to test using interface collection with Rhino.Mocks

In my interface
public IMyListInterface : IList<IMyItem>
{
void Foo();
}
how can I easily create an example for testing classes that use IMyListInterface.
Currently I'm using GenerateStub<MyListInterface>() and delegating the needed methods / properties to a List<IMyItem> list but it's tedious.
Currently to get the following code under test to work
foreach (var match in matchList)
I'm doing the following in my test class
IList<IMyItem> baseList = new List<IMyItem>();
IMyListInterface matchList = MockRepository.GenerateStub<IMyListInterface>();
matchList.Stub(m => m.GetEnumerator()).Return(null).WhenCalled(i => i.ReturnValue = baseList.GetEnumerator());
Is there a better way?
Implement the interface in an abstract base class for testing:
public abstract MyMockableList : List<MyItem>, IMyListInterface
{
public abstract void Foo();
}
You can then use MockRepository.GenerateStub<MyMockableList>(), which will function as a normal list (RhinoMocks won't override the methods inherited from List<MyItem>) but you can still stub out the Foo() method.

How to unit test works in salesforce?

I've done writing code on salesforce and in order to release the unit tests have to cover at least 75%.
What I am facing is that the classOne that calls methods from classTwo also have to cover classTwo's unit test within classOne even though it is done in classTwo file already.
File MyClassTwo
public with sharing class ClassTwo {
public String method1() {
return 'one';
}
public String method2() {
return 'two';
}
public static testMethod void testMethod1() {
ClassTwo two = new ClassTwo();
String out = two.method1();
system.assertEquals(out, 'one'); //valid
}
public static testMethod void testMethod2() {
ClassTwo two = new ClassTwo();
String out = two.method2();
system.assertEquals(out, 'two'); // valid
}
}
File MyClassOne
public with sharing class ClassOne {
public String callClassTwo() {
ClassTwo foo = new ClassTwo();
String something = foo.method1();
return something;
}
public static testMethod void testCallClassTwo() {
ClassOne one = new ClassOne();
String out = one.callClassTwo();
system.assertEquals(out, 'one');
}
}
The result of testing MyClassOne would not return 100% test coverage because it says I have not covered MyClassTwo method2() part inside of MyClassOne file.
But I already wrote unit test for MyClassTwo inside of MyClassTwo file as you can see.
So does this mean I have to copy and paste the unit test in MyClassTwo file over to MyClassOne?
Doing so gives me 100% coverage but this seems really annoying and rediculous. Having same test in ClassA and ClassB....? Am I doing wrong or is this the way?
Having said, is it possible to create mock object in salesforce? I haven't figure how yet..
http://sites.force.com/answers/ideaView?c=09a30000000D9xt&id=087300000007m3fAAA&returnUrl=/apex/ideaList%3Fc%3D09a30000000D9xt%26category%3DApex%2B%2526%2BVisualforce%26p%3D19%26sort%3Dpopular
UDPATE
I re-wrote the code and updated above, this time for sure classOne test would not return 100% even though it is not calling classTwo method2()
Comments about Java mock libraries aren't very helpful in Salesforce world ;) At my projects we usually aimed for making our own test data in the test method, calling real functionality, checking the results... and whole test framework on Salesforce side is responsible for transaction rollback (so no test data is saved to DB in the end regardless whether the test failed or passed).
Anyway...
Masato, your classes do not compile (methods outside class scope, public String hello() without any String returned)... After I fixed it I simply right-clicked the MyClassA -> Force.com -> run tests and got full code coverage without any problems so your issue must lie somewhere else...
Here's how it looks: http://dl.dropbox.com/u/709568/stackoverflow/masato_code_coverage.png
I'm trying to think what might have gone wrong... are you sure all classes compile and were saved on server side? Did you put test methods in same classes as functionality or in separate ones (generally I make separate class name with similar name like MyClassATest). If it's a separate class - on which file did you click "run tests"?
Last but not least - if you're facing this issue during deployment from sandbox to production, make sure you selected all classes you need in the deployment wizard?
If you really want to "unit" test, you should test the behavior of your class B AND the behavior of your class A, mocking the call to the class B method.
That's a tough conversation between mock lovers and others (Martin Fowler I think is not a "mocker").
Anyway. You should stop thinking about 100% coverage. You should think about:
Why am i testing?
How am i testing?
Here, i'd definitely go for 2 tests:
One test for the B class into the b class test file to be sure the B method is well implemented, with all the side effects, side values etc.
one test for the A class mocking the class B
What is a mock?
To stay VERY simple: A mock is a portion of code in your test which is gonna say: when the B class method is called, always return this value: "+++" .
By doing this, you allow yourself having a maintanable and modulable test suite.
In java, I love mockito : http://mockito.org/
Although one of my colleagues is lead maintainer for easymock: http://easymock.org/
Hope this helps. Ask me if you need further help.
EDIT SOME EXAMPLE
With Java and mockito:
public class aUTest {
protected A a;
#Mock protected B b;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
a = new A();
ReflectionTestUtils.setField(a, "b", b);
}
#Test
public void test_A_method_should_not_throw_exception()
when(b. execute()).thenReturn(true); //just an example of a return value from b. execute()
Boolean result = a.testHello();
// Assert
Assert.assertEquals(true, result);
}
I created an Apex class called TestHelper for all my mock objects. I use constants (static final) for values that I might need elsewhere and public static fields for objects. Works great and since no methods are used, no test coverage is needed.
public without sharing class TestHelper {
public static final string testPRODUCTNAME = 'test Product Name';
public static final string testCOMPANYID = '2508';
public static Account testAccount {
get{
Account tAccount = new Account(
Name = 'Test Account',
BillingStreet = '123 Main St',
BillingCity = 'Dallas',
BillingState = 'TX',
BillingPostalCode = '75234',
Website = 'http://www.google.com',
Phone = '222 345 4567',
Subscription_Start_Date__c = system.today(),
Subscription_End_Date__c = system.today().addDays(30),
Number_Of_Seats__c = 1,
companyId__c = testCOMPANYID,
ZProduct_Name__c = testPRODUCTNAME);
insert tAccount;
return tAccount;
}
}
}