You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Janne Jalkanen <ja...@ecyrd.com> on 2010/11/08 21:20:11 UTC

Weird unit testing problem

Folks,

I'm rather stymied at the following problem: Whenever I run my unit tests one at a time, everything works. But when I run the entire suite, the tests fail due to 

        SecurityUtils.getSubject().logout(); // Ensure we are logged out
        SecurityUtils.getSubject().login( new UsernamePasswordToken("test@thinglink.com","foobar") );
 
The failure is 

org.apache.shiro.authc.IncorrectCredentialsException: The credentials provided for account [org.apache.shiro.authc.UsernamePasswordToken - jj@thinglink.com, rememberMe=false] did not match the expected credentials.
	at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:191)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:179)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:264)
	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
	at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:269)
	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:247)
	at com.thinglink.site.stripes.AccountActionBeanTest.setup(AccountActionBeanTest.java:43)
<rest is snipped away>

I've tried different kinds of Shiro configurations, and the one that seems to work best right now looks like

    /** Configuration that we use in tests. */
    private static final String SHIRO_CONFIG = 
        "[main]\n"+
        "credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher\n"+
        "credentialsMatcher.storedCredentialsHexEncoded = false\n"+
        "credentialsMatcher.hashSalted = true\n"+
        "cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager\n"+
        "myRealm = com.thinglink.site.shiro.CassandraRealm\n"+
        "myRealm.credentialsMatcher = $credentialsMatcher\n"+
        "myRealm.cacheManager = $cacheManager\n"+
        "securityManager = org.apache.shiro.mgt.DefaultSecurityManager\n"+
        "securityManager.realm = $myRealm\n";

// For shiro we use our internal configuration, not the one that's found from classpath
        Ini ini = new Ini();
        ini.load( SHIRO_CONFIG );
        IniSecurityManagerFactory smf = new IniSecurityManagerFactory( ini );
        SecurityUtils.setSecurityManager( smf.getInstance() );

I've tried using a WebIniSecurityManagerFactory, but the test framework I'm using does not fully implement the Servlet spec, so it's not that useful; it fails in interesting ways and getting cookies is a pain.  So I figured I should try just simply the basic DefaultSecurityManager as everything runs in a single thread anyway.

This is with 1.1.0 release.

Any ideas as to what could explain why the tests aren't running if I run all the tests? The fun thing is that this is the *only* test currently which actively tries to log in.

/Janne

Re: Weird unit testing problem

Posted by Janne Jalkanen <ja...@ecyrd.com>.
> It's useful to think through the whole scenario. If we actually
> prevented this, it'd mean that Shiro couldn't be reconfigured
> dynamically within the same JVM. Logging a warning perhaps (I'm sure
> there are at least some info messages on this even currently) but how
> much configuration would be enough configuration to trigger a warning?
> I'll certainly evaluate concrete suggestions to mitigate this but
> until then it's business as usual: if you run unit tests within the
> same JVM better make sure they don't interfere with each other.

The thing is - I *though* I was making sure they don't interfere. I reinitialized Shiro on every test, and it turns out that you can't dynamically reconfigure Shiro within the same JVM. However, this was a wrong assumption, and a log message would've helped on it.  Not to mention a more helpful exception...

/Janne

Re: Weird unit testing problem

Posted by Kalle Korhonen <ka...@gmail.com>.
On Tue, Nov 9, 2010 at 12:47 AM, Janne Jalkanen
<ja...@ecyrd.com> wrote:
> And to respond to myself - the problem turns out to be that I had one
> instance where Shiro was configured implicitly and not using the
> SHIRO_CONFIG below. Turns out that this causes a conflict if you configure
> Shiro twice with different settings within the same JVM.
> It would be good if there was some sort of a check for this - the exception
> message is not exactly helping here.

It's useful to think through the whole scenario. If we actually
prevented this, it'd mean that Shiro couldn't be reconfigured
dynamically within the same JVM. Logging a warning perhaps (I'm sure
there are at least some info messages on this even currently) but how
much configuration would be enough configuration to trigger a warning?
I'll certainly evaluate concrete suggestions to mitigate this but
until then it's business as usual: if you run unit tests within the
same JVM better make sure they don't interfere with each other.

Kalle


> Folks,
> I'm rather stymied at the following problem: Whenever I run my unit tests
> one at a time, everything works. But when I run the entire suite, the tests
> fail due to
>         SecurityUtils.getSubject().logout(); // Ensure we are logged out
>         SecurityUtils.getSubject().login( new
> UsernamePasswordToken("test@thinglink.com","foobar") );
>
> The failure is
> org.apache.shiro.authc.IncorrectCredentialsException: The credentials
> provided for account [org.apache.shiro.authc.UsernamePasswordToken -
> jj@thinglink.com, rememberMe=false] did not match the expected credentials.
> at
> org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:191)
> at
> org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:179)
> at
> org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:264)
> at
> org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
> at
> org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
> at
> org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:269)
> at
> org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:247)
> at
> com.thinglink.site.stripes.AccountActionBeanTest.setup(AccountActionBeanTest.java:43)
> <rest is snipped away>
> I've tried different kinds of Shiro configurations, and the one that seems
> to work best right now looks like
>     /** Configuration that we use in tests. */
>     private static final String SHIRO_CONFIG =
>         "[main]\n"+
>         "credentialsMatcher =
> org.apache.shiro.authc.credential.Sha256CredentialsMatcher\n"+
>         "credentialsMatcher.storedCredentialsHexEncoded = false\n"+
>         "credentialsMatcher.hashSalted = true\n"+
>         "cacheManager =
> org.apache.shiro.cache.MemoryConstrainedCacheManager\n"+
>         "myRealm = com.thinglink.site.shiro.CassandraRealm\n"+
>         "myRealm.credentialsMatcher = $credentialsMatcher\n"+
>         "myRealm.cacheManager = $cacheManager\n"+
>         "securityManager = org.apache.shiro.mgt.DefaultSecurityManager\n"+
>         "securityManager.realm = $myRealm\n";
> // For shiro we use our internal configuration, not the one that's found
> from classpath
>         Ini ini = new Ini();
>         ini.load( SHIRO_CONFIG );
>         IniSecurityManagerFactory smf = new IniSecurityManagerFactory( ini
> );
>         SecurityUtils.setSecurityManager( smf.getInstance() );
> I've tried using a WebIniSecurityManagerFactory, but the test framework I'm
> using does not fully implement the Servlet spec, so it's not that useful; it
> fails in interesting ways and getting cookies is a pain.  So I figured I
> should try just simply the basic DefaultSecurityManager as everything runs
> in a single thread anyway.
> This is with 1.1.0 release.
> Any ideas as to what could explain why the tests aren't running if I run all
> the tests? The fun thing is that this is the *only* test currently which
> actively tries to log in.
> /Janne
>

Re: Weird unit testing problem

Posted by Les Hazlewood <lh...@apache.org>.
Hi Janne,

I threw this together today:

http://shiro.apache.org/testing.html

Feedback is welcome.  I hope it helps!

Best,

Les

On Sun, Nov 21, 2010 at 8:03 AM, Janne Jalkanen
<Ja...@ecyrd.com> wrote:
>
> Yup, this answers quite a few of my questions. Any chance this could be put
> somewhere as a part of the official documentation as well?
> Thanks heaps, tests are now running perfectly :-)
> /Janne
> On Nov 9, 2010, at 21:02 , Les Hazlewood wrote:
>
> Shiro can be configured dynamically in a single JVM - I do it all the time
> on a product I'm working on. I guess it means what you mean by 'configure
> dynamically'.  I'm not swapping out the security manager entirely however.
>  I re-configure the same instance (maybe swap out its AuthorizationStrategy,
> etc).
> When a Subject instance is created (a DelegatingSubject specifically), it
> accepts a SecurityManager instance at that time. It holds on to that
> instance throughout it's lifetime.  In other words, you can call
> SecurityUtils.setSecurityManager at any time after that point (which sets a
> VM-static singleton) and the previously instantiated Subject instance(s)
> will not 'see' the new static SecurityManager instance.
> Subject object instances themselves are intended to have a very short VM
> lifetime - typically instantiated at the beginning of a thread's execution
> and removed/garbage collected at the end of its execution.  Swapping out a
> SecurityManager entirely during a thread's execution is not something that
> people have requested in the past, so we haven't built it.  I'm not sure how
> often this would occur in practice for running applications to be honest.
> So to sidestep this for unit testing scenarios, there are two good
> approaches that I can think of:
> 1)  Use a Subject.Builder and pass in the SecurityManager instance you want
> it to use during the test.  The constructed instance is used to 'execute' a
> method under test:
> Subject subject = new Subject.Builder(mySecurityManager).buildSubject();
> subject.execute( new Runnable() {
>     executeMethodUnderTest();
> });
> When 'executeMethodUnderTest' executes, the subject.execute method will
> guarantee thread set-up and clean-up before and after the method's
> execution, respectively.  Also, any call to SecurityUtils.getSubject()
> within that method (or any methods it calls) will work correctly.
> 2) Set up and tear down the Shiro thread state before and after a test
> methods's execution.  This is the exact same thing as #1, but requires you
> to do a little more work.  See
> the http://shiro.apache.org/subject.html page, "Manual Association" section
> for more detail.  You would do this in @Before and @After methods in JUnit:
> private ThreadState shiroThreadState;
> @Before
> public void setUpSubject() {
>     Subject testSubject = Subject.Builder(securityManagerForTheTest). ...
> .buildSubject();
>     shiroThreadState = new SubjectThreadState(testSubject);
>     shiroThreadState.bind();
> }
> @After
> public void tearDownSubject() {
>     shiroThreadState.restore();  //or clear(); either is fine.
> }
> #1 is easier, but it might make your test cases look a little ugly.  #2 is a
> little more time consuming, but more flexible and arguably nicer when
> keeping your tests clean.  You can have this in a test superclass and your
> subclasses wouldn't ever have to worry about it.  They could call
> SecurityUtils.getSubject() at any time and it would all work out.
> Note that the Subject.Builder constructor doesn't require a securityManager
> instance - if you don't provide one, it will call
> SecurityUtils.getSecurityManager() and use that one instead.  I typically
> like to specify the instance myself because I personally don't like using
> static singletons if I can avoid them, and at least in testing, I find it to
> be a bit more deterministic.
> Anyway, I hope this helps.  Does this all make sense?
> Best,
> --
> Les Hazlewood
> Founder, Katasoft, Inc.
> Application Security Products & Professional Apache Shiro Support and
> Training:
> http://www.katasoft.com
> On Tue, Nov 9, 2010 at 12:47 AM, Janne Jalkanen <ja...@ecyrd.com>
> wrote:
>>
>> And to respond to myself - the problem turns out to be that I had one
>> instance where Shiro was configured implicitly and not using the
>> SHIRO_CONFIG below. Turns out that this causes a conflict if you configure
>> Shiro twice with different settings within the same JVM.
>> It would be good if there was some sort of a check for this - the
>> exception message is not exactly helping here.
>> /Janne
>> On 8 Nov 2010, at 22:20, Janne Jalkanen wrote:
>>
>> Folks,
>> I'm rather stymied at the following problem: Whenever I run my unit tests
>> one at a time, everything works. But when I run the entire suite, the tests
>> fail due to
>>         SecurityUtils.getSubject().logout(); // Ensure we are logged out
>>         SecurityUtils.getSubject().login( new
>> UsernamePasswordToken("test@thinglink.com","foobar") );
>>
>> The failure is
>> org.apache.shiro.authc.IncorrectCredentialsException: The credentials
>> provided for account [org.apache.shiro.authc.UsernamePasswordToken -
>> jj@thinglink.com, rememberMe=false] did not match the expected credentials.
>> at
>> org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:191)
>> at
>> org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:179)
>> at
>> org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:264)
>> at
>> org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
>> at
>> org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
>> at
>> org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:269)
>> at
>> org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:247)
>> at
>> com.thinglink.site.stripes.AccountActionBeanTest.setup(AccountActionBeanTest.java:43)
>> <rest is snipped away>
>> I've tried different kinds of Shiro configurations, and the one that seems
>> to work best right now looks like
>>     /** Configuration that we use in tests. */
>>     private static final String SHIRO_CONFIG =
>>         "[main]\n"+
>>         "credentialsMatcher =
>> org.apache.shiro.authc.credential.Sha256CredentialsMatcher\n"+
>>         "credentialsMatcher.storedCredentialsHexEncoded = false\n"+
>>         "credentialsMatcher.hashSalted = true\n"+
>>         "cacheManager =
>> org.apache.shiro.cache.MemoryConstrainedCacheManager\n"+
>>         "myRealm = com.thinglink.site.shiro.CassandraRealm\n"+
>>         "myRealm.credentialsMatcher = $credentialsMatcher\n"+
>>         "myRealm.cacheManager = $cacheManager\n"+
>>         "securityManager = org.apache.shiro.mgt.DefaultSecurityManager\n"+
>>         "securityManager.realm = $myRealm\n";
>> // For shiro we use our internal configuration, not the one that's found
>> from classpath
>>         Ini ini = new Ini();
>>         ini.load( SHIRO_CONFIG );
>>         IniSecurityManagerFactory smf = new IniSecurityManagerFactory( ini
>> );
>>         SecurityUtils.setSecurityManager( smf.getInstance() );
>> I've tried using a WebIniSecurityManagerFactory, but the test framework
>> I'm using does not fully implement the Servlet spec, so it's not that
>> useful; it fails in interesting ways and getting cookies is a pain.  So I
>> figured I should try just simply the basic DefaultSecurityManager as
>> everything runs in a single thread anyway.
>> This is with 1.1.0 release.
>> Any ideas as to what could explain why the tests aren't running if I run
>> all the tests? The fun thing is that this is the *only* test currently which
>> actively tries to log in.
>> /Janne

Re: Weird unit testing problem

Posted by Janne Jalkanen <Ja...@ecyrd.com>.
Yup, this answers quite a few of my questions. Any chance this could be put somewhere as a part of the official documentation as well?

Thanks heaps, tests are now running perfectly :-)

/Janne

On Nov 9, 2010, at 21:02 , Les Hazlewood wrote:

> Shiro can be configured dynamically in a single JVM - I do it all the time on a product I'm working on. I guess it means what you mean by 'configure dynamically'.  I'm not swapping out the security manager entirely however.  I re-configure the same instance (maybe swap out its AuthorizationStrategy, etc).
> 
> When a Subject instance is created (a DelegatingSubject specifically), it accepts a SecurityManager instance at that time. It holds on to that instance throughout it's lifetime.  In other words, you can call SecurityUtils.setSecurityManager at any time after that point (which sets a VM-static singleton) and the previously instantiated Subject instance(s) will not 'see' the new static SecurityManager instance.
> 
> Subject object instances themselves are intended to have a very short VM lifetime - typically instantiated at the beginning of a thread's execution and removed/garbage collected at the end of its execution.  Swapping out a SecurityManager entirely during a thread's execution is not something that people have requested in the past, so we haven't built it.  I'm not sure how often this would occur in practice for running applications to be honest.
> 
> So to sidestep this for unit testing scenarios, there are two good approaches that I can think of:
> 
> 1)  Use a Subject.Builder and pass in the SecurityManager instance you want it to use during the test.  The constructed instance is used to 'execute' a method under test:
> 
> Subject subject = new Subject.Builder(mySecurityManager).buildSubject();
> subject.execute( new Runnable() {
>     executeMethodUnderTest();
> });
> 
> When 'executeMethodUnderTest' executes, the subject.execute method will guarantee thread set-up and clean-up before and after the method's execution, respectively.  Also, any call to SecurityUtils.getSubject() within that method (or any methods it calls) will work correctly.
> 
> 2) Set up and tear down the Shiro thread state before and after a test methods's execution.  This is the exact same thing as #1, but requires you to do a little more work.  See the http://shiro.apache.org/subject.html page, "Manual Association" section for more detail.  You would do this in @Before and @After methods in JUnit:
> 
> private ThreadState shiroThreadState;
> 
> @Before
> public void setUpSubject() {
>     Subject testSubject = Subject.Builder(securityManagerForTheTest). ... .buildSubject();
>     shiroThreadState = new SubjectThreadState(testSubject);
>     shiroThreadState.bind();
> }
> 
> @After
> public void tearDownSubject() {
>     shiroThreadState.restore();  //or clear(); either is fine.
> }
> 
> #1 is easier, but it might make your test cases look a little ugly.  #2 is a little more time consuming, but more flexible and arguably nicer when keeping your tests clean.  You can have this in a test superclass and your subclasses wouldn't ever have to worry about it.  They could call SecurityUtils.getSubject() at any time and it would all work out.
> 
> Note that the Subject.Builder constructor doesn't require a securityManager instance - if you don't provide one, it will call SecurityUtils.getSecurityManager() and use that one instead.  I typically like to specify the instance myself because I personally don't like using static singletons if I can avoid them, and at least in testing, I find it to be a bit more deterministic.
> 
> Anyway, I hope this helps.  Does this all make sense?
> 
> Best,
> 
> -- 
> Les Hazlewood
> Founder, Katasoft, Inc.
> Application Security Products & Professional Apache Shiro Support and Training:
> http://www.katasoft.com
> 
> On Tue, Nov 9, 2010 at 12:47 AM, Janne Jalkanen <ja...@ecyrd.com> wrote:
> 
> And to respond to myself - the problem turns out to be that I had one instance where Shiro was configured implicitly and not using the SHIRO_CONFIG below. Turns out that this causes a conflict if you configure Shiro twice with different settings within the same JVM.
> 
> It would be good if there was some sort of a check for this - the exception message is not exactly helping here.
> 
> /Janne
> 
> On 8 Nov 2010, at 22:20, Janne Jalkanen wrote:
> 
>> Folks,
>> 
>> I'm rather stymied at the following problem: Whenever I run my unit tests one at a time, everything works. But when I run the entire suite, the tests fail due to 
>> 
>>         SecurityUtils.getSubject().logout(); // Ensure we are logged out
>>         SecurityUtils.getSubject().login( new UsernamePasswordToken("test@thinglink.com","foobar") );
>>  
>> The failure is 
>> 
>> org.apache.shiro.authc.IncorrectCredentialsException: The credentials provided for account [org.apache.shiro.authc.UsernamePasswordToken - jj@thinglink.com, rememberMe=false] did not match the expected credentials.
>> 	at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:191)
>> 	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:179)
>> 	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:264)
>> 	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
>> 	at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
>> 	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:269)
>> 	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:247)
>> 	at com.thinglink.site.stripes.AccountActionBeanTest.setup(AccountActionBeanTest.java:43)
>> <rest is snipped away>
>> 
>> I've tried different kinds of Shiro configurations, and the one that seems to work best right now looks like
>> 
>>     /** Configuration that we use in tests. */
>>     private static final String SHIRO_CONFIG = 
>>         "[main]\n"+
>>         "credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher\n"+
>>         "credentialsMatcher.storedCredentialsHexEncoded = false\n"+
>>         "credentialsMatcher.hashSalted = true\n"+
>>         "cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager\n"+
>>         "myRealm = com.thinglink.site.shiro.CassandraRealm\n"+
>>         "myRealm.credentialsMatcher = $credentialsMatcher\n"+
>>         "myRealm.cacheManager = $cacheManager\n"+
>>         "securityManager = org.apache.shiro.mgt.DefaultSecurityManager\n"+
>>         "securityManager.realm = $myRealm\n";
>> 
>> // For shiro we use our internal configuration, not the one that's found from classpath
>>         Ini ini = new Ini();
>>         ini.load( SHIRO_CONFIG );
>>         IniSecurityManagerFactory smf = new IniSecurityManagerFactory( ini );
>>         SecurityUtils.setSecurityManager( smf.getInstance() );
>> 
>> I've tried using a WebIniSecurityManagerFactory, but the test framework I'm using does not fully implement the Servlet spec, so it's not that useful; it fails in interesting ways and getting cookies is a pain.  So I figured I should try just simply the basic DefaultSecurityManager as everything runs in a single thread anyway.
>> 
>> This is with 1.1.0 release.
>> 
>> Any ideas as to what could explain why the tests aren't running if I run all the tests? The fun thing is that this is the *only* test currently which actively tries to log in.
>> 
>> /Janne


Re: Weird unit testing problem

Posted by Les Hazlewood <lh...@apache.org>.
Shiro can be configured dynamically in a single JVM - I do it all the time
on a product I'm working on. I guess it means what you mean by 'configure
dynamically'.  I'm not swapping out the security manager entirely however.
 I re-configure the same instance (maybe swap out its AuthorizationStrategy,
etc).

When a Subject instance is created (a DelegatingSubject specifically), it
accepts a SecurityManager instance at that time. It holds on to that
instance throughout it's lifetime.  In other words, you can call
SecurityUtils.setSecurityManager at any time after that point (which sets a
VM-static singleton) and the previously instantiated Subject instance(s)
will not 'see' the new static SecurityManager instance.

Subject object instances themselves are intended to have a very short VM
lifetime - typically instantiated at the beginning of a thread's execution
and removed/garbage collected at the end of its execution.  Swapping out a
SecurityManager entirely during a thread's execution is not something that
people have requested in the past, so we haven't built it.  I'm not sure how
often this would occur in practice for running applications to be honest.

So to sidestep this for unit testing scenarios, there are two good
approaches that I can think of:

1)  Use a Subject.Builder and pass in the SecurityManager instance you want
it to use during the test.  The constructed instance is used to 'execute' a
method under test:

Subject subject = new Subject.Builder(mySecurityManager).buildSubject();
subject.execute( new Runnable() {
    executeMethodUnderTest();
});

When 'executeMethodUnderTest' executes, the subject.execute method will
guarantee thread set-up and clean-up before and after the method's
execution, respectively.  Also, any call to SecurityUtils.getSubject()
within that method (or any methods it calls) will work correctly.

2) Set up and tear down the Shiro thread state before and after a test
methods's execution.  This is the exact same thing as #1, but requires you
to do a little more work.  See the http://shiro.apache.org/subject.html page,
"Manual Association" section for more detail.  You would do this in @Before
and @After methods in JUnit:

private ThreadState shiroThreadState;

@Before
public void setUpSubject() {
    Subject testSubject = Subject.Builder(securityManagerForTheTest). ...
.buildSubject();
    shiroThreadState = new SubjectThreadState(testSubject);
    shiroThreadState.bind();
}

@After
public void tearDownSubject() {
    shiroThreadState.restore();  //or clear(); either is fine.
}

#1 is easier, but it might make your test cases look a little ugly.  #2 is a
little more time consuming, but more flexible and arguably nicer when
keeping your tests clean.  You can have this in a test superclass and your
subclasses wouldn't ever have to worry about it.  They could call
SecurityUtils.getSubject() at any time and it would all work out.

Note that the Subject.Builder constructor doesn't require a securityManager
instance - if you don't provide one, it will call
SecurityUtils.getSecurityManager() and use that one instead.  I typically
like to specify the instance myself because I personally don't like using
static singletons if I can avoid them, and at least in testing, I find it to
be a bit more deterministic.

Anyway, I hope this helps.  Does this all make sense?

Best,

-- 
Les Hazlewood
Founder, Katasoft, Inc.
Application Security Products & Professional Apache Shiro Support and
Training:
http://www.katasoft.com

On Tue, Nov 9, 2010 at 12:47 AM, Janne Jalkanen <ja...@ecyrd.com>wrote:

>
> And to respond to myself - the problem turns out to be that I had one
> instance where Shiro was configured implicitly and not using the
> SHIRO_CONFIG below. Turns out that this causes a conflict if you configure
> Shiro twice with different settings within the same JVM.
>
> It would be good if there was some sort of a check for this - the exception
> message is not exactly helping here.
>
> /Janne
>
> On 8 Nov 2010, at 22:20, Janne Jalkanen wrote:
>
> Folks,
>
> I'm rather stymied at the following problem: Whenever I run my unit tests
> one at a time, everything works. But when I run the entire suite, the tests
> fail due to
>
>         SecurityUtils.*getSubject*().logout(); // Ensure we are logged out
>         SecurityUtils.*getSubject*().login( *new* UsernamePasswordToken("
> test@thinglink.com","foobar") );
>
> The failure is
>
> org.apache.shiro.authc.IncorrectCredentialsException: The credentials
> provided for account [org.apache.shiro.authc.UsernamePasswordToken -
> jj@thinglink.com, rememberMe=false] did not match the expected
> credentials.
> at
> org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:191)
> at
> org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:179)
> at
> org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:264)
> at
> org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
> at
> org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
> at
> org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:269)
> at
> org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:247)
> at
> com.thinglink.site.stripes.AccountActionBeanTest.setup(AccountActionBeanTest.java:43)
> <rest is snipped away>
>
> I've tried different kinds of Shiro configurations, and the one that seems
> to work best right now looks like
>
>     /** Configuration that we use in tests. */
>     *private* *static* *final* String *SHIRO_CONFIG* =
>         "[main]\n"+
>         "credentialsMatcher =
> org.apache.shiro.authc.credential.Sha256CredentialsMatcher\n"+
>         "credentialsMatcher.storedCredentialsHexEncoded = false\n"+
>         "credentialsMatcher.hashSalted = true\n"+
>         "cacheManager =
> org.apache.shiro.cache.MemoryConstrainedCacheManager\n"+
>         "myRealm = com.thinglink.site.shiro.CassandraRealm\n"+
>         "myRealm.credentialsMatcher = $credentialsMatcher\n"+
>         "myRealm.cacheManager = $cacheManager\n"+
>         "securityManager = org.apache.shiro.mgt.DefaultSecurityManager\n"+
>         "securityManager.realm = $myRealm\n";
>
> // For shiro we use our internal configuration, not the one that's found
> from classpath
>         Ini ini = *new* Ini();
>         ini.load( *SHIRO_CONFIG* );
>         IniSecurityManagerFactory smf = *new* IniSecurityManagerFactory(
> ini );
>         SecurityUtils.*setSecurityManager*( smf.getInstance() );
>
> I've tried using a WebIniSecurityManagerFactory, but the test framework I'm
> using does not fully implement the Servlet spec, so it's not that useful; it
> fails in interesting ways and getting cookies is a pain.  So I figured I
> should try just simply the basic DefaultSecurityManager as everything runs
> in a single thread anyway.
>
> This is with 1.1.0 release.
>
> Any ideas as to what could explain why the tests aren't running if I run
> all the tests? The fun thing is that this is the *only* test currently which
> actively tries to log in.
>
> /Janne
>
>

Re: Weird unit testing problem

Posted by Janne Jalkanen <ja...@ecyrd.com>.
And to respond to myself - the problem turns out to be that I had one instance where Shiro was configured implicitly and not using the SHIRO_CONFIG below. Turns out that this causes a conflict if you configure Shiro twice with different settings within the same JVM.

It would be good if there was some sort of a check for this - the exception message is not exactly helping here.

/Janne

On 8 Nov 2010, at 22:20, Janne Jalkanen wrote:

> Folks,
> 
> I'm rather stymied at the following problem: Whenever I run my unit tests one at a time, everything works. But when I run the entire suite, the tests fail due to 
> 
>         SecurityUtils.getSubject().logout(); // Ensure we are logged out
>         SecurityUtils.getSubject().login( new UsernamePasswordToken("test@thinglink.com","foobar") );
>  
> The failure is 
> 
> org.apache.shiro.authc.IncorrectCredentialsException: The credentials provided for account [org.apache.shiro.authc.UsernamePasswordToken - jj@thinglink.com, rememberMe=false] did not match the expected credentials.
> 	at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:191)
> 	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:179)
> 	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:264)
> 	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
> 	at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
> 	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:269)
> 	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:247)
> 	at com.thinglink.site.stripes.AccountActionBeanTest.setup(AccountActionBeanTest.java:43)
> <rest is snipped away>
> 
> I've tried different kinds of Shiro configurations, and the one that seems to work best right now looks like
> 
>     /** Configuration that we use in tests. */
>     private static final String SHIRO_CONFIG = 
>         "[main]\n"+
>         "credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher\n"+
>         "credentialsMatcher.storedCredentialsHexEncoded = false\n"+
>         "credentialsMatcher.hashSalted = true\n"+
>         "cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager\n"+
>         "myRealm = com.thinglink.site.shiro.CassandraRealm\n"+
>         "myRealm.credentialsMatcher = $credentialsMatcher\n"+
>         "myRealm.cacheManager = $cacheManager\n"+
>         "securityManager = org.apache.shiro.mgt.DefaultSecurityManager\n"+
>         "securityManager.realm = $myRealm\n";
> 
> // For shiro we use our internal configuration, not the one that's found from classpath
>         Ini ini = new Ini();
>         ini.load( SHIRO_CONFIG );
>         IniSecurityManagerFactory smf = new IniSecurityManagerFactory( ini );
>         SecurityUtils.setSecurityManager( smf.getInstance() );
> 
> I've tried using a WebIniSecurityManagerFactory, but the test framework I'm using does not fully implement the Servlet spec, so it's not that useful; it fails in interesting ways and getting cookies is a pain.  So I figured I should try just simply the basic DefaultSecurityManager as everything runs in a single thread anyway.
> 
> This is with 1.1.0 release.
> 
> Any ideas as to what could explain why the tests aren't running if I run all the tests? The fun thing is that this is the *only* test currently which actively tries to log in.
> 
> /Janne